/* global Descartes */
var Utils = Descartes.Utils;
var UI = Descartes.UI;
var ConfirmDialog = Descartes.ConfirmDialog;

var _ = require('lodash');
var printerSetupTemplate = require('./templates/InkMapSetup.ejs');

/**
 * Class: Descartes.UI.AbstractPrinterSetup
 * Classe "abstraite" proposant la saisie des paramètres de mise en page pour l'exportation PDF.
 *
 * :
 * Le formulaire de saisie est constitué de zones de texte (marges) et d'une liste déroulante (format).
 *
 * Hérite de:
 *  - <Descartes.UI>
 *
 * Classes dérivées:
 *  - <Descartes.UI.PrinterSetupDialog>
 *  - <Descartes.UI.PrinterSetupInPlace>
 */
var Class = Utils.Class(UI, {
    /**
     * Propriete: errors
     * {Array(String)} Liste des erreurs rencontrés lors des contrôles de surface.
     */
    errors: null,

    /**
     * Propriete: form
     * {DOMElement} Elément DOM correspondant au formulaire de saisie.
     */
    form: null,

    /**
     * Propriete: papers
     * {Array(Object)} Objets JSON stockant les propriétés des "papiers" disponibles en cohérence avec la taille de la carte.
     */
    papers: [],

    /**
     * Propriete: resolutions
     * {Array(number)} Les résolutions proposée pour imprimer la carte.
     */
    resolutions: [],

    /**
     * Propriete: projections
     * {Array(number)} Les projections proposée pour imprimer la carte.
     */
     projections: [],

    /**
     * Propriete: size
     * {Integer} Taille des zones de saisie (10 par défaut).
     */
    size: 10,

    panelCss: null,

    EVENT_TYPES: ['startPrint', 'changePaperSize', 'togglePreview', 'toggleBlock'],

    /**
     * Constructeur: Descartes.UI.AbstractPrinterSetup
     * Constructeur d'instances
     *
     * Paramètres:
     * div - {DOMElement|String} Elément DOM de la page accueillant le formulaire de saisie.
     * paramsModel - {Object} Modèle de la vue passé par référence par le contrôleur <Descartes.Action.PrinterParamsManager>.
     * options - {Object} Objet optionnel contenant les propriétés à renseigner dans l'instance
     *
     * Options de construction propres à la classe:
     * size - {Integer} Taille des zones de saisie (10 par défaut).
     */
    initialize: function (div, paramsModel, options) {
        this.panelCss = Descartes.UIBootstrap4Options.panelCss;
        UI.prototype.initialize.apply(this, [div, paramsModel, this.EVENT_TYPES, options]);
    },

    /**
     * Methode: setPapers
     * Construit la liste des "papiers" disponibles à partir du modèle transmis par le contrôleur.
     */
    setPapers: function () {
        this.papers = [];
        for (var i = 0, len = this.model.enabledFormats.length; i < len; i++) {
            var format = this.model.enabledFormats[i];
            var text = format.code.substring(0, format.code.length - 1);
            text += (format.code.substring(format.code.length - 1) === "L") ? this.getMessage("LANDSCAPE_OPTION") : this.getMessage("PORTRAIT_OPTION");
            this.papers.push({
                value: format.code,
                text: text,
                paperWidth: format.width,
                paperHeight: format.height
            });
        }
    },

    /**
     * Methode: setResolutions
     * Initialize la liste des résolutions.
     */
    setResolutions: function () {
        this.resolutions = [90, 150, 300];
    },

    /**
     * Methode: setProjections
     * Initialize la liste des projections.
     */
    setProjections: function () {
        this.projections = [];
        if (this.model.projectionEditable && this.model.displayProjections && this.model.displayProjections.length > 0) {
           for (var j = 0, jlen = this.model.displayProjections.length; j < jlen; j++) {
               this.projections.push({code: this.model.displayProjections[j], value: Utils.getProjectionName(this.model.displayProjections[j])});
           }
        }
    },

    /**
     * Methode: populateForm
     * Construit les zones de saisie du formulaire.
     */
    populateForm: function () {
        return printerSetupTemplate(_.extend({
            panelCss: this.panelCss,
            paperInput: this.getMessage("PAPER_INPUT"),
            papers: this.papers,
            dpiInput: this.getMessage("DPI_INPUT"),
            resolutions: this.resolutions,
            projectionInput: this.getMessage("PROJECTION_INPUT"),
            projections: this.projections,
            selectedProjection: this.model.selectedDisplayProjectionIndex,
            marginsGroupInput: this.getMessage("MARGINS_GROUP_INPUT"),
            marginTopInput: this.getMessage("MARGIN_TOP_INPUT"),
            marginBottomInput: this.getMessage("MARGIN_BOTTOM_INPUT"),
            marginLeftInput: this.getMessage("MARGIN_LEFT_INPUT"),
            marginRightInput: this.getMessage("MARGIN_RIGHT_INPUT"),
            printLegendLabel: this.getMessage("PRINT_LEGEND"),
            printProjectionLabel: this.getMessage("PRINT_PROJECTION"),
            printScaleLabel: this.getMessage("PRINT_SCALE"),
            printNorthLabel: this.getMessage("PRINT_NORTH"),
            printTitleLabel: this.getMessage("PRINT_TITLE"),
            printDescriptionLabel: this.getMessage("PRINT_DESCRIPTION"),
            printDateLabel: this.getMessage("PRINT_DATE"),
            printQRLabel: this.getMessage("PRINT_QR"),
            showPrintPreviewMessage: this.getMessage('SHOW_PREVIEW_MESSAGE')
        }, this.model));
    },

    /**
     * Methode: done
     * Transmet le modèle au contrôleur, en déclenchant l'événement 'startPrint', ou affiche les messages d'erreur rencontrés.
     */
    done: function () {
        if (this.validateDatas()) {
            this.events.triggerEvent('startPrint');
        } else {
            this.showErrors();
        }
    },

    /**
     * Methode: validateDatas
     * Effectue les contrôles de surface après la saisie.
     *
     * :
     * Met à jour le modèle si ceux-ci sont assurés.
     *
     * :
     * Alimente la liste des erreurs dans le cas contraire.
     */
    validateDatas: function () {
        this.errors = [];
        if (this.result.marginTopInput) {
            this.model.marginTop = parseInt(this.result.marginTopInput, 10);
            if (isNaN(this.model.marginTop) || this.model.marginTop < 0) {
                this.errors.push(this.getMessage('MARGIN_TOP_ERROR'));
            }
        }
        if (this.result.marginBottomInput) {
            this.model.marginBottom = parseInt(this.result.marginBottomInput, 10);
            if (isNaN(this.model.marginBottom) || this.model.marginBottom < 0) {
                this.errors.push(this.getMessage('MARGIN_BOTTOM_ERROR'));
            }
        }
        if (this.result.marginLeftInput) {
            this.model.marginLeft = parseInt(this.result.marginLeftInput, 10);
            if (isNaN(this.model.marginLeft) || this.model.marginLeft < 0) {
                this.errors.push(this.getMessage('MARGIN_LEFT_ERROR'));
            }
        }
        if (this.result.marginRightInput) {
            this.model.marginRight = parseInt(this.result.marginRightInput, 10);
            if (isNaN(this.model.marginRight) || this.model.marginRight < 0) {
                this.errors.push(this.getMessage('MARGIN_RIGHT_ERROR'));
            }
        }
        return (this.errors.length === 0);
    },

    /**
     * Methode: showErrors
     * Affiche la liste des erreurs rencontrés lors des contrôles de surface.
     */
    showErrors: function () {
        if (this.errors.length !== 0) {

            var errorsMessage = '<ul>';
            for (var i = 0, len = this.errors.length; i < len; i++) {
                errorsMessage += '<li>' + this.errors[i] + '</li>';
            }
            errorsMessage += '</ul>';
            var dialog = new ConfirmDialog({
                id: this.id + '_confirmDialog',
                title: this.getMessage('ERRORS_LIST'),
                message: errorsMessage,
                type: 'default'
            });
            dialog.open();
        }
    },

    CLASS_NAME: 'Descartes.UI.AbstractInkMapSetup'
});

module.exports = Class;
