/*****************************************************************************\
|                                               ( )_  _                       |
|    _ _    _ __   _ _    __    ___ ___     _ _ | ,_)(_)  ___   ___     _     |
|   ( '_`\ ( '__)/'_` ) /'_ `\/' _ ` _ `\ /'_` )| |  | |/',__)/' _ `\ /'_`\   |
|   | (_) )| |  ( (_| |( (_) || ( ) ( ) |( (_| || |_ | |\__, \| ( ) |( (_) )  |
|   | ,__/'(_)  `\__,_)`\__  |(_) (_) (_)`\__,_)`\__)(_)(____/(_) (_)`\___/'  |
|   | |                ( )_) |                                                |
|   (_)                 \___/'                                                |
|                                                                             |
| General Bots Copyright (c) Pragmatismo.io. All rights reserved.             |
| Licensed under the AGPL-3.0.                                                |
|                                                                             | 
| According to our dual licensing model, this program can be used either      |
| under the terms of the GNU Affero General Public License, version 3,        |
| or under a proprietary license.                                             |
|                                                                             |
| The texts of the GNU Affero General Public License with an additional       |
| permission and of our proprietary license can be found at and               |
| in the LICENSE file you have received along with this program.              |
|                                                                             |
| This program is distributed in the hope that it will be useful,             |
| but WITHOUT ANY WARRANTY; without even the implied warranty of              |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the                |
| GNU Affero General Public License for more details.                         |
|                                                                             |
| "General Bots" is a registered trademark of Pragmatismo.io.                 |
| The licensing of the program under the AGPLv3 does not imply a              |
| trademark license. Therefore any rights, title and interest in              |
| our trademarks remain entirely with us.                                     |
|                                                                             |
\*****************************************************************************/

const Path = require("path");
const Fs = require("fs");
const _ = require("lodash");
const Parse = require("csv-parse");
const Async = require("async");
const UrlJoin = require("url-join");
const Walk = require("fs-walk");
const logger = require("../../../src/logger");
const Swagger = require('swagger-client');
const rp = require('request-promise');
import * as request from "request-promise-native";

import { GBServiceCallback, GBService, IGBInstance } from "botlib";

export class ConsoleDirectLine extends GBService {

    pollInterval = 1000;
    directLineSecret = '';
    directLineClientName = 'DirectLineClient';
    directLineSpecUrl = 'https://docs.botframework.com/en-us/restapi/directline3/swagger.json';

    constructor(directLineSecret) {
        super();

        this.directLineSecret = directLineSecret;


        // TODO: Migrate to Swagger 3.
        let directLineClient = rp(this.directLineSpecUrl)
            .then(function (spec) {
                return new Swagger({
                    spec: JSON.parse(spec.trim()),
                    usePromise: true
                });
            })
            .then(function (client) {
                client.clientAuthorizations.add('AuthorizationBotConnector',
                    new Swagger.ApiKeyAuthorization('Authorization', 'Bearer ' + directLineSecret, 'header'));
                return client;
            })
            .catch(function (err) {
                console.error('Error initializing DirectLine client', err);
            });

        // TODO: Remove *this* issue.
        let _this_ = this;
        directLineClient.then(function (client) {
            client.Conversations.Conversations_StartConversation()
                .then(function (response) {
                    return response.obj.conversationId;
                })
                .then(function (conversationId) {
                    _this_.sendMessagesFromConsole(client, conversationId);
                    _this_.pollMessages(client, conversationId);
                })
                .catch(function (err) {
                    console.error('Error starting conversation', err);
                });
        });
    }

    sendMessagesFromConsole(client, conversationId) {
        let _this_ = this;
        process.stdin.resume();
        var stdin = process.stdin;
        process.stdout.write('Command> ');
        stdin.addListener('data', function (e) {
            var input = e.toString().trim();
            if (input) {
                // exit
                if (input.toLowerCase() === 'exit') {
                    return process.exit();
                }

                client.Conversations.Conversations_PostActivity(
                    {
                        conversationId: conversationId,
                        activity: {
                            textFormat: 'plain',
                            text: input,
                            type: 'message',
                            from: {
                                id: _this_.directLineClientName,
                                name: _this_.directLineClientName
                            }
                        }
                    }).catch(function (err) {
                        console.error('Error sending message:', err);
                    });

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

    /** TBD: Poll Messages from conversation using DirectLine client */
    pollMessages(client, conversationId) {
        let _this_ = this;
        console.log('Starting polling message for conversationId: ' + conversationId);
        var watermark = null;
        setInterval(function () {
            client.Conversations.Conversations_GetActivities({ conversationId: conversationId, watermark: watermark })
                .then(function (response) {
                    watermark = response.obj.watermark;                                 // use watermark so subsequent requests skip old messages
                    return response.obj.activities;
                })
                .then(_this_.printMessages, _this_.directLineClientName);
        }, this.pollInterval);
    }

    printMessages(activities, directLineClientName) {

        if (activities && activities.length) {
            // ignore own messages
            activities = activities.filter(function (m) { return m.from.id !== directLineClientName });

            if (activities.length) {

                // print other messages
                activities.forEach(activity => {
                    console.log(activity.text);
                });

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

    printMessage(activity) {
        if (activity.text) {
            console.log(activity.text);
        }

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

                    case "image/png":
                        console.log('Opening the requested image ' + attachment.contentUrl);
                        open(attachment.contentUrl);
                        break;
                }
            });
        }
    }

    renderHeroCard(attachment) {
        var width = 70;
        var contentLine = function (content) {
            return ' '.repeat((width - content.length) / 2) +
                content +
                ' '.repeat((width - content.length) / 2);
        }

        console.log('/' + '*'.repeat(width + 1));
        console.log('*' + contentLine(attachment.content.title) + '*');
        console.log('*' + ' '.repeat(width) + '*');
        console.log('*' + contentLine(attachment.content.text) + '*');
        console.log('*'.repeat(width + 1) + '/');
    }



}