/* eslint max-len: ["error", { "code": 180 }]*/
const got = require('got');
const UserError = require('vn-loopback/util/user-error');

module.exports = Self => {
    Self.remoteMethodCtx('download', {
        description: 'Download an docuware PDF',
        accessType: 'READ',
        accepts: [
            {
                arg: 'id',
                type: 'number',
                description: 'The id',
                http: {source: 'path'}
            },
            {
                arg: 'fileCabinet',
                type: 'string',
                description: 'The id',
                http: {source: 'path'}
            },
            {
                arg: 'dialog',
                type: 'string',
                description: 'The id',
                http: {source: 'path'}
            }
        ],
        returns: [
            {
                arg: 'body',
                type: 'file',
                root: true
            }, {
                arg: 'Content-Type',
                type: 'string',
                http: {target: 'header'}
            }, {
                arg: 'Content-Disposition',
                type: 'string',
                http: {target: 'header'}
            }
        ],
        http: {
            path: `/:id/download/:fileCabinet/:dialog`,
            verb: 'GET'
        }
    });

    Self.download = async function(ctx, id, fileCabinet, dialog) {
        const myUserId = ctx.req.accessToken.userId;
        if (!myUserId)
            throw new UserError(`You don't have enough privileges`);

        const models = Self.app.models;
        const docuwareConfig = await models.DocuwareConfig.findOne();
        const docuwareInfo = await models.Docuware.findOne({
            where: {
                code: fileCabinet,
                dialogName: dialog
            }
        });

        const docuwareUrl = docuwareConfig.url;
        const cookie = docuwareConfig.token;
        const fileCabinetName = docuwareInfo.fileCabinetName;
        const find = docuwareInfo.find;
        const options = {
            'headers': {
                'Accept': 'application/json',
                'Content-Type': 'application/json',
                'Cookie': cookie
            }
        };
        const searchFilter = {
            condition: [
                {
                    DBName: find,
                    Value: [id]
                }
            ]
        };

        try {
            // get fileCabinetId
            const fileCabinetResponse = await got.get(`${docuwareUrl}/FileCabinets`, options);
            const fileCabinetJson = JSON.parse(fileCabinetResponse.body).FileCabinet;
            const fileCabinetId = fileCabinetJson.find(dialogs => dialogs.Name === fileCabinetName).Id;

            // get dialog
            const dialogResponse = await got.get(`${docuwareUrl}/FileCabinets/${fileCabinetId}/dialogs`, options);
            const dialogJson = JSON.parse(dialogResponse.body).Dialog;
            const dialogId = dialogJson.find(dialogs => dialogs.DisplayName === 'find').Id;

            // get docuwareID
            Object.assign(options, {'body': JSON.stringify(searchFilter)});
            const response = await got.post(`${docuwareUrl}/FileCabinets/${fileCabinetId}/Query/DialogExpression?dialogId=${dialogId}`, options);
            const docuwareId = JSON.parse(response.body).Items[0].Id;

            // download & save file
            const fileName = `filename="${id}.pdf"`;
            const contentType = 'application/pdf';
            const downloadUri = `${docuwareUrl}/FileCabinets/${fileCabinetId}/Documents/${docuwareId}/FileDownload?targetFileType=Auto&keepAnnotations=false`;
            const downloadOptions = {
                'headers': {
                    'Cookie': cookie
                }
            };

            const stream = got.stream(downloadUri, downloadOptions);

            return [stream, contentType, fileName];
        } catch (error) {
            if (error.code === 'ENOENT')
                throw new UserError('The DOCUWARE PDF document does not exists');

            throw error;
        }
    };
};