/**
 *  Multilingual System
 *
 *  Last version: 05 Mar 2017
 *  Author: Bruno Torrinha <http://www.torrinha.com>
 *
 *  MIT License
 *
 *  Provides a mechanism for easily manage multi languages on a single page.
 *  It was created for the BREAD system of Cms, but can be implemented
 *  with any html structure.
 *  For each translatable field, the page requires an hidden input containing
 *  all translations in JSON format.
 *
 *  Some considerations:
 *  Every time a translatable model is opened, all languages are being loaded.
 *  This may work well with few languages, but in case of 20+, it may require
 *  another approach, like using AJAX.
 *
 *  TO-DO
 *  * Google Translator, triggered by a subtle link placed somewhere near the input.
 *  * Option for Показано a fall-back version of the field, under the input.
 *    This would apply to text input only.
 *
 */
;( function( $, window, document, undefined ) {

    "use strict";

        var pluginName = "multilingual",
            defaults = {
                editing:       false,                       // Editing or View
                form:          '.form-edit-add',
                transInputs:   'input[data-i18n = true]',   // Hidden inputs holding translations
                langSelectors: '> .language-selector input' // Language selector inputs
            };

        function Plugin ( element, options ) {
            this.element   = $(element);
            this.settings  = $.extend( {}, defaults, options );
            this._defaults = defaults;
            this._name     = pluginName;
            this.init();
        }

        $.extend( Plugin.prototype, {
            init: function() {
                this.form          = this.element.find(this.settings.form);
                this.transInputs   = $(this.settings.transInputs);
                this.langSelectors = this.element.find(this.settings.langSelectors);

                if (this.transInputs.length === 0 || this.langSelectors === 0) {
                    return false;
                }
                this.setup();
                this.refresh();
            },


            setup: function() {
                var _this = this;

                this.locale = this.returnLocale();

                /**
                 * Setup language selector
                 */
                this.langSelectors.each(function(i, btn) {
                    $(btn).change($.proxy(_this.selectLanguage, _this));
                });

                /**
                 * Save data before submit
                 */
                if (this.settings.editing) {
                    $(this.form).on('submit', function(e) {
                        e.preventDefault();
                        _this.prepareData();
                        $(_this.form)[0].submit();
                    });
                }
            },

            /**
             * Refresh plugin data, required for dynamic calls (ex menu)
             */
            refresh: function() {
                var _this = this;

                /**
                 * Setup translatable inputs
                 */
                this.transInputs.each(function(i, inp) {
                    var _inp   = $(inp),
                        inpUsr = _inp.next(_this.settings.editing ? '.form-control' : '');

                    inpUsr.data("inp", _inp);
                    _inp.data("inpUsr", inpUsr);

                    // Load and Save data in hidden input
                    var $_data = _this.loadJsonField(_inp.val());
                    if (_this.settings.editing) {
                        _inp.val(JSON.stringify($_data));
                    }

                    _this.langSelectors.each(function(i, btn) {
                        _inp.data(btn.id, $_data[btn.id]);  // Save translation in mem
                        if (btn.id == _this.locale) {
                            _this.loadLang(_inp, btn.id)    // Load active locale
                        }
                    });
                });
            },

            loadJsonField: function(str) {
                var $_data = {};
                if (this.isJsonValid(str)) {
                    return JSON.parse(str);
                }

                return $_data;
            },


            isJsonValid: function(str) {
                try {
                    JSON.parse(str);
                } catch (ex) {
                    return false;
                }
                return true;
            },

            /**
             * Return Locale for a given Button Group Selector
             *
             * @return string The locale.
             */
            returnLocale: function() {
                return this.langSelectors.filter(function() {
                    return $(this).parent().hasClass('active');
                }).prop('id');
            },

            selectLanguage: function(e) {
                var _this = this,
                    lang  = e.target.id;

                this.transInputs.each(function(i, inp) {
                    if (_this.settings.editing) {
                        _this.updateInputCache($(inp));
                    }
                    _this.loadLang($(inp), lang);
                });

                this.locale = lang;
            },

            /**
             * Update cache for all inputs, and prepare form data for submit
             */
            prepareData: function() {
                var _this = this;
                this.transInputs.each(function(i, inp) {
                    _this.updateInputCache($(inp));
                });
            },

            /**
             * Update cache for a single input
             */
            updateInputCache: function(inp) {
                var _this  = this,
                    inpUsr = inp.data('inpUsr'),
                    $_val  = $(inpUsr).val(),
                    $_data = {};  // Create new data

                if (inpUsr.hasClass('richTextBox')) {
                    var $_mce = tinymce.get('richtext'+inpUsr.prop('name'));
                    $_val = $_mce.getContent();
                }

                this.langSelectors.each(function(i, btn) {
                    var lang = btn.id;
                    $_data[lang] = (_this.locale == lang) ? $_val : inp.data(lang);
                });

                inp.val(JSON.stringify($_data));
                inp.data(this.locale, $_val);     // Update single key Mem
            },

            /**
             * Load input translation
             */
            loadLang: function(inp, lang) {
                var inpUsr = inp.data("inpUsr"),
                    _val   = inp.data(lang);

                if (!this.settings.editing) {
                    inpUsr.text(_val);
                } else {
                    var $richtext = 'richtext'+inpUsr.prop('name');
                    if (inpUsr.hasClass('richTextBox') && tinymce.get($richtext)) {
                        tinymce.get($richtext).setContent(_val);
                    } else {
                        inpUsr.val(_val);
                    }
                }
            }
        });

        $.fn[ pluginName ] = function( options ) {
            return this.each( function() {
                if ( !$.data( this, pluginName ) ) {
                    $.data( this, pluginName, new Plugin(this, options) );
                }
            } );
        };

} )( jQuery, window, document );
