const Swagger = require('swagger-client');
const rp = require('request-promise');
import { GBLog, GBService } from 'botlib';

/**
 * Bot simulator in terminal window.
 */
export class ConsoleDirectLine extends GBService {
  public pollInterval: number = 1000;
  public directLineSecret: string = '';
  public directLineClientName: string = 'DirectLineClient';
  public directLineSpecUrl: string = 'https://docs.botframework.com/en-us/restapi/directline3/swagger.json';

  constructor(directLineSecret: string) {
    super();

    this.directLineSecret = directLineSecret;
    // tslint:disable-next-line:no-unsafe-any
    const directLineClient = rp(this.directLineSpecUrl)
      .then((spec: string) => {
        // tslint:disable-next-line:no-unsafe-any
        return new Swagger({
          spec: JSON.parse(spec.trim()),
          usePromise: true
        });
      })
      .then(client => {
        // tslint:disable-next-line:no-unsafe-any
        client.clientAuthorizations.add(
          'AuthorizationBotConnector',
          // tslint:disable-next-line:no-unsafe-any
          new Swagger.ApiKeyAuthorization('Authorization', `Bearer ${directLineSecret}`, 'header')
        );

        return client;
      })
      .catch(err => {
        GBLog.error(`Error initializing DirectLine client ${err}`);
      });

    const _this_ = this;
    // tslint:disable-next-line:no-unsafe-any
    directLineClient.then(client => {
      // tslint:disable-next-line:no-unsafe-any
      client.Conversations.Conversations_StartConversation()
        .then(response => {
          // tslint:disable-next-line:no-unsafe-any
          return response.obj.conversationId;
        })
        .then(conversationId => {
          _this_.sendMessagesFromConsole(client, conversationId);
          _this_.pollMessages(client, conversationId);
        })
        .catch(err => {
          GBLog.error(`Error starting conversation ${err}`);
        });
    });
  }

  public sendMessagesFromConsole(client, conversationId) {
    const _this_ = this;
    process.stdin.resume();
    const stdin = process.stdin;
    process.stdout.write('Command> ');
    stdin.addListener('data', e => {
      // tslint:disable-next-line:no-unsafe-any
      const input: string = e.toString().trim();
      if (input !== undefined) {
        // exit
        if (input.toLowerCase() === 'exit') {
          return process.exit();
        }

        // tslint:disable-next-line:no-unsafe-any
        client.Conversations.Conversations_PostActivity({
          conversationId: conversationId,
          activity: {
            textFormat: 'plain',
            text: input,
            type: 'message',
            from: {
              id: _this_.directLineClientName,
              name: _this_.directLineClientName
            }
          }
        }).catch(err => {
          GBLog.error(`Error sending message: ${err}`);
        });

        process.stdout.write('Command> ');
      }
    });
  }

  public pollMessages(client, conversationId) {
    const _this_ = this;
    GBLog.info(`Starting polling message for conversationId: ${conversationId}`);
    let watermark;
    setInterval(() => {
      // tslint:disable-next-line:no-unsafe-any
      client.Conversations.Conversations_GetActivities({ conversationId: conversationId, watermark: watermark })
        .then(response => {
          // tslint:disable-next-line:no-unsafe-any
          watermark = response.obj.watermark;

          // tslint:disable-next-line:no-unsafe-any
          return response.obj.activities;
        })
        .then(_this_.printMessages, _this_.directLineClientName);
      // tslint:disable-next-line:align
    }, this.pollInterval);
  }

  // tslint:disable:no-unsafe-any
  public printMessages(activities, directLineClientName) {
    if (activities && activities.length) {
      // ignore own messages
      activities = activities.filter(m => {
        return m.from.id !== directLineClientName;
      });

      if (activities.length) {
        // print other messages
        activities.forEach(activity => {
          GBLog.info(activity.text);
          // tslint:disable-next-line:align
        }, this);

        process.stdout.write('Command> ');
      }
    }
  }
  // tslint:enable:no-unsafe-any

  // tslint:disable:no-unsafe-any
  public printMessage(activity) {
    if (activity.text) {
      GBLog.info(activity.text);
    }

    if (activity.attachments) {
      activity.attachments.forEach(attachment => {
        switch (attachment.contentType) {
          case 'application/vnd.microsoft.card.hero':
            this.renderHeroCard(attachment);
            break;

          case 'image/png':
            GBLog.info(`Opening the requested image ${attachment.contentUrl}`);
            open(attachment.contentUrl);
            break;

          default:
            GBLog.info(`Unknown contentType: ${attachment.contentType}`);
            break;
        }
      });
    }
  }
  // tslint:enable:no-unsafe-any

  // tslint:disable:no-unsafe-any
  public renderHeroCard(attachment) {
    const width = 70;
    const contentLine = content => {
      return `${' '.repeat((width - content.length) / 2)}content${' '.repeat((width - content.length) / 2)}`;
    };

    GBLog.info(`/${'*'.repeat(width + 1)}`);
    GBLog.info(`*${contentLine(attachment.content.title)}*`);
    GBLog.info(`*${' '.repeat(width)}*`);
    GBLog.info(`*${contentLine(attachment.content.text)}*`);
    GBLog.info(`${'*'.repeat(width + 1)}/`);
  }
  // tslint:enable:no-unsafe-any
}
