/*globals window, define*/
/*jslint nomen:true, unparam: true*/

/**
 * Open a dialog to edit custom form fields.
 *
 * The `.customformUiCustomform()` method opens a dialog when the element is clicked. The dialog can be used to edit new custom form fields.
 * The element has to contain two data attributes, data-formfieldid (representing the ID for the form field type, e.g. textarea, select ..) and data-objectid (representing the ID of the existing form field).
 *
 * ### Examples
 * Edit a existing custom form field
 *
 * JavaScript:
 *
 *
 *     de_epages('.editCustomField').customformUiCustomform({
 *         width: 800,
 *         height: 400,
 *         languageId: 1,
 *         languages: {'2' : 'English', '1' : 'Deutsch'},
 *         afterSaveDialog: function (widget, data){
 *             console.debug(widget, data);
 *         }
 *     });
 *
 * HTML:
 *
 *     <a href="#" class="editCustomField" data-formfieldid="5094" data-objectid="16211">Feldname</a>
 *
 *
 * @class jQuery.ui.customformUiCustomform
 * @extends jQuery.widget
 *
 * @uses ep
 * @uses jQuery.dict
 * @uses jQuery.fn.scrollTo
 * @uses ep.dict
 * @uses jQuery.tmpl
 * @uses jQuery.metaparse
 * @uses jQuery.ui.widget
 * @uses ep.ui.dialog
 * @uses ep.ui.validate
 * @uses ep.validate
 * @since 6.15.0
 */

/**
 * @cfg {Integer} [width] An integer representing the width of the dialog.
 */

/**
 * @cfg {Integer} [height] An integer representing the height of the dialog.
 */

/**
 * @cfg {Integer} [languageId] An integer respresenting the ID of the currently active language.
 */

/**
 * @cfg {Object} [languages] A object representing the languages (id-name pairs, e.g. {'2' : 'English', '1' : 'Deutsch'}).
 */

/**
 * @cfg {Object} [afterSaveDialog] Callback function which is called after the new form field values were successfully saved.
 */

/**
 * See `jQuery.ui.customformUiCustomform` for details.
 *
 * @param {Object} [options] A map of additional options pass to the method.
 * @param {Integer} [width] An integer representing the width of the dialog.
 * @param {Integer} [height] An integer representing the height of the dialog.
 * @param {Integer} [languageId] An integer respresenting the ID of the currently active language.
 * @param {Object} [languages] A object representing the languages (id-name pairs, e.g. {'2' : 'English', '1' : 'Deutsch'}).
 * @param {Object} [afterSaveDialog] Callback function which is called after the new form field values were successfully saved.
 *
 * @method customformUiCustomform
 * @member jQuery
 *
 * @since 6.15.0
 */

/*
 * @copyright       © Copyright 2006-2012, epages GmbH, All Rights Reserved.
 *
 * @module          de_epages.customform.ui.customform
 *
 * @revision        $Revision: 1.11 $
 */

define("de_epages/customform/ui/customform", [
    "jquery",
    "ep",
    "de_epages",
    "$dict!../dictionary",
    "$tmpl!./customform-edit",
    "$tmpl!./customform-newoption",

    "jquery/metaparse",
    "jquery/fn/scrollto",
    "jquery/ui/widget",
    "ep/validate",
    "ep/ui/dialog",
    "ep/ui/validate"
], function ($, ep, de_epages, customformDict, tmplCustomformEdit, tmplCustomformNewoption) {
    'use strict';

    /*
     * @dictionary      ep.dict
     *
     * @translation     {Type}
     *                              {MandatoryStar}
     *                              {yes}
     *                              {no}
     *                              {Apply}
     *                              {Cancel}
     *
     * @dictionary      de_epages.customform.dictionary
     *
     * @translation     {FieldName}
     *                              {MandatoryForUsers}
     *                              {AdditionalFormFieldText}
     *                              {EditFormField}
     *                              {HeaderRadioOptions}
     *                              {HeaderSelectOptions}
     *                              {AddFormFieldOption}
     *                              {NewOption}
     */

    var translationsDialog = {
            tType: customformDict.translate('Type'),
            tYes: customformDict.translate('yes'),
            tNo: customformDict.translate('no'),
            tAdd: customformDict.translate('Apply'),
            tCancel: customformDict.translate('Cancel'),
            tTitle: customformDict.translate('EditFormField'),
            tFieldName: customformDict.translate('FieldName'),
            tMandatoryStar: customformDict.translate('MandatoryStar'),
            tMandatoryForUsers: customformDict.translate('MandatoryForUsers'),
            tAdditionalFormFieldText: customformDict.translate('AdditionalFormFieldText'),
            tHeaderRadioOptions: customformDict.translate('HeaderRadioOptions'),
            tHeaderSelectOptions: customformDict.translate('HeaderSelectOptions'),
            tAddFormFieldOption: customformDict.translate('AddFormFieldOption'),
            tNewOption: customformDict.translate('NewOption')
        };

    $.widget('ui.customformUiCustomform', {
        //  _newOptionCounter: undefined,
        //  ObjectID: undefined,

        // default options
        options: {
            ViewAction: 'JSONGetFieldData',
            dialogContentId: 'editDialogContent',
            isPreview: false,
            languages: {},
            languageId: 1,
            width: 800,
            height: 400
        },

        _create: function () {
            var self = this,
                elem = self.element,
                o = self.options;

            // get the object ID
            self.ObjectID = elem.data('objectid');
            // get the form field ID
            self.FormFieldID = elem.data('formfieldid');

            // get the mandatory checkbox
            if (!o.isPreview) {
                self._mandatoryField = $("input[value=" + self.ObjectID + "][name=IsMandatoryObjectID]");
            }

            // handle click to open dialog to edit form field
            elem.on('click', function (event) {
                // remove already existing dialog
                if ($('#' + o.dialogContentId).length) {
                    $('#' + o.dialogContentId).remove();
                }

                self.dialogContentHolder = ep('<div id="' + o.dialogContentId + '" />');
                self.dialogContentHolder.appendTo('body');

                // create dialog to edit form field
                self.dialog = self.dialogContentHolder.uiDialog({
                    title: translationsDialog.tTitle + ": ",
                    modal: true,
                    width: o.width,
                    height: o.height,
                    position: ['center', $('window').scrollTop() + 30],
                    form: {
                        action: '?',
                        method: 'post',
                        options: {
                            ajax: function (send) {
                                send({
                                    dataType: 'json',
                                    data: {
                                        ChangeAction: "JSONAlterField",
                                        ObjectID: self.ObjectID,
                                        ChangeObjectID: self.ObjectID,
                                        FormFieldID: self.FormFieldID,
                                        FieldClassID: self.FormFieldID
                                    }
                                })
                                    .done(function (data, status, jqXHR) {
                                        // uncomment next line for debug use
                                        //console.log("done:", data);

                                        // widget was called from preview
                                        if (o.isPreview) {
                                            // execute callback
                                            if (typeof o.afterSaveDialog === "function") {
                                                o.afterSaveDialog(self, data);
                                            }
                                        } else {
                                            // set mandatory checkbox if necessary
                                            if (data.IsMandatory !== self._isMandatory) {
                                                self._mandatoryField.prop('checked', !self._isMandatory);
                                            }

                                            // set field name if necessary
                                            var rewriteFieldName = data.FieldName || data.Alias;
                                            if (self._fieldName !== rewriteFieldName) {
                                                $('#alterLink_' + self.ObjectID).html(rewriteFieldName);
                                            }
                                        }

                                        self.dialogContentHolder.uiDialog('close');
                                    });
                            }
                        }
                    },
                    open: function () {
                        // get data from server
                        self._getFieldData();
                    },
                    buttons: [{
                        type: "submit",
                        text: translationsDialog.tAdd
                    }, {
                        text: translationsDialog.tCancel,
                        click: function () {
                            ep(this).uiDialog('close');
                        }
                    }]
                });

                // handle form errors for FieldNames (at least one field is requested)
                self.form = self.dialog.uiDialog('option', 'form')
                    .on('submit', function (event) {
                        if (self.Alias !== "CaptionFormField") {
                            var elem = $(this),
                                first,
                                isInvalid = true;

                            elem
                                .find('input[name=FieldName]')
                                .each(function (i) {
                                    var input = ep(this);

                                    // remember first input
                                    if (i === 0) {
                                        first = input;
                                    }
                                    // if a not empty input was found -> mark as valid and leave each
                                    if (input.val() !== "") {
                                        isInvalid = false;
                                        return false;
                                    }
                                });

                            if (isInvalid) {
                                first
                                    .uiValidate({required: true})
                                    .trigger('focus')
                                    .trigger('validate');

                                event.preventDefault();
                            } else {
                                first
                                    .uiValidate({required: false})
                                    .trigger('validate');
                            }
                        }
                    });

            });
        },

        _getFieldData: function () {
            var self = this,
                o = self.options;

            ep.ajax({
                dataType: 'json',
                data: {
                    ViewAction: o.ViewAction,
                    ObjectID    : self.ObjectID
                }
            })
                .done(function (data) {
                    self.Alias = data.Alias;
                    // mandatory on start up
                    self._isMandatory = parseInt(data.IsMandatory, 10);

                    if (!o.isPreview) {
                        // check if mandatory value from document is the same as the requested one
                        self._isMandatory = (self._mandatoryField.is(':checked') === !!self._isMandatory) ? self._isMandatory : [1, 0][self._isMandatory];
                    }
                    data.IsMandatory = self._isMandatory;

                    // get the fieldname for the custom form field (for default language)
                    $.each(data.LocalizedTexts, function (key, value) {
                        if (o.languageId === value.LanguageID) {
                            self._fieldName = value.FieldName;
                            return false;
                        }
                    });

                    // save original data
                    self.currentData = data;
                    // process request data
                    self._processFieldData(data);

                })
                .fail(function (xhr, status, error) {
                    // ToDo: something more
                    // console.warn(error);
                    return;
                });
        },

        _processFieldData: function () {
            var self = this,
                elem = self.element,
                o = self.options;

            if (self.dialog === undefined) {
                self.dialog = self.dialogContentHolder.uiDialog();
            }

            // extend currentData with additional attributes as default language id, type name and language object (key == languageId)
            $.extend(self.currentData, {
                languageId: o.languageId,
                alias: self.currentData.NameOrAlias[o.languageId],
                languages: o.languages
            });

            // complete dialog title with field name
            var fieldname = (elem.closest('dl')[0] && elem.closest('dl').data('fieldname')) ? elem.closest('dl').data('fieldname') : undefined;
            fieldname = (fieldname === undefined) ? elem.text() : fieldname;
            self.dialog.uiDialog('option', 'title', self.dialog.uiDialog('option', 'title') + " " + fieldname);

            // append necessary template to dialog
            tmplCustomformEdit($.extend(self.currentData, translationsDialog)).appendTo(self.dialogContentHolder);
            // resolve metaparse parts in dialog
            ep('#' + o.dialogContentId + ' *').metaparse();

            // if custom form field needs handling for options
            if (self.currentData.HasOptions) {
                // initialize counter for new options
                self._newOptionCounter = 0;
                // get DOM element which holds all options (new options get the class "epCustomFormAddNewOption")
                self.optionsHolder = self.dialog.find('.epCustomFormOptions');

                // delete options
                self.optionsHolder.find('a[data-deleteoptionid]').on('click', function (evt) {
                    var _this = $(this),
                        form = $(this).closest('form'),
                        hidden = $('<input type="hidden" name="DeleteOptionID" value="' + _this.data('deleteoptionid') + '" />');

                    // fade out parent table row
                    _this.closest('li').fadeOut();
                    // add hidden input containing delete information (send and deleted when "Save" is pressed)
                    hidden.appendTo(form);

                    // prevent default action for preview
                    if (o.isPreview) {
                        evt.preventDefault();
                    }
                });

                // delete new added options
                self.optionsHolder.on('click', 'a.deleteNewOptionLink', function (evt) {
                    var _this = $(this);

                    // fade out parent table row
                    _this.closest('li').slideUp(500, function () {
                        $(this).remove();
                    });

                    // prevent default action for preview
                    if (o.isPreview) {
                        evt.preventDefault();
                    }
                });

                // get DOM element to add a new option and set an event handler
                self.newOptionLink = self.dialog.find('#addNewOptionLink');
                self.newOptionLink.on('click', function (evt) {
                    self._handleNewOption();
                });
            }
        },

        _handleNewOption: function () {
            var self = this;

            // increment new option counter
            self._newOptionCounter++;

            // append template for new option to dialog
            tmplCustomformNewoption(self.currentData, {count: self._newOptionCounter}).appendTo(self.optionsHolder);

            var lastOptionElement = self.optionsHolder.children(':last');
            // fade new option element in
            lastOptionElement.fadeIn(500, function () {
                // resolve metaparse parts in template
                ep(lastOptionElement.find('input')).metaparse();
                // move next animation to another thread
                window.setTimeout(function () {
                    // scroll down to last option element
                    self.optionsHolder.scrollTo(lastOptionElement, 800);
                }, 1);
            });
        }
    });

    return de_epages;

});