/* Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
'use strict';

// Form service
angular.module('flowableModeler').service('FormBuilderService', ['$http', '$q', '$rootScope', '$translate',
    function ($http, $q, $rootScope, $translate) {

        // Removes all properties starting with '_', used before json serialization
        function removePrivateFields(fields) {
            fields.forEach(function(field, i){
                for (var attr in field) {
                    if (attr.indexOf('_') === 0) {
                        delete field[attr];
                    }
                }
                if (field.fields) {
                    for (var fieldsName in field.fields) {
                        removePrivateFields(field.fields[fieldsName]);
                    }
                }
            });
            return fields;
        }

        /**
         * Remove the given step from the given container.
         */
        this.saveForm = function (data, name, formKey, description, saveCallback, errorCallback) {

            var fieldIndex = 0;
            data.formRepresentation = $rootScope.currentForm;
            data.formRepresentation.name = name;
            data.formRepresentation.key = formKey;

            if (description && description.length > 0) {
                data.formRepresentation.description = description;
            }
            for (var i = 0; i < $rootScope.formItems.length; i++) {
                var field = $rootScope.formItems[i];
                this._cleanFormField(field, fieldIndex++);
            }

            var currentActiveTab = $rootScope.formBuilder.activeTab;
            if (currentActiveTab != 'design') {
                $rootScope.formBuilder.activeTab = 'design';
            }

            data.formRepresentation.formDefinition = {
            	name: name,
            	key: formKey,
            	fields: removePrivateFields(angular.copy($rootScope.formItems)), 
            	outcomes: $rootScope.currentOutcomes
            };

            html2canvas(jQuery('#canvasSection'), {
                onrendered: function (canvas) {
                    var scale = canvas.width / 300.0;
                    var extra_canvas = document.createElement("canvas");
                    extra_canvas.setAttribute('width', 300);
                    extra_canvas.setAttribute('height', canvas.height / scale);
                    var ctx = extra_canvas.getContext('2d');
                    ctx.drawImage(canvas, 0, 0, canvas.width, canvas.height, 0, 0, 300, canvas.height / scale);
                    data.formImageBase64 = extra_canvas.toDataURL("image/png");

                    $http({method: 'PUT', url: FLOWABLE.APP_URL.getFormModelUrl($rootScope.currentForm.id), data: data}).
                        success(function (response, status, headers, config) {

                            if (saveCallback) {
                                saveCallback();
                            }
                        }).
                        error(function (response, status, headers, config) {
                            if (errorCallback) {
                                errorCallback(response);
                            }
                        });

                    if (currentActiveTab != 'design') {
                        $rootScope.formBuilder.activeTab = currentActiveTab;
                    }
                }
            });
        };
        
        this._cleanFormField = function(field, fieldIndex) {
            if (!field.overrideId) {
                var fieldId;
                if (field.name && field.name.length > 0) {
                    fieldId = field.name.toLowerCase();
                    fieldId = fieldId.replace(new RegExp(' ', 'g'), '');
                    fieldId = fieldId.replace(/[&\/\\#,+~%.'":*?!<>{}()$@;]/g, '');
                } else {
                    fieldId = 'field' + fieldIndex;
                }
                field.id = fieldId;
            }
        };

        /**
         * Updates the form cache for a specific step
         * @param {String} stepId
         * @param {Object} formDefinition
         */
        this.updateFormsCache = function (stepId, formDefinition) {
            if (stepId) {
                if (formDefinition && formDefinition.id) {
                    _updateFormCache(stepId, formDefinition.id);
                } else {
                    _updateFormCache(stepId);
                }
            }
        };

        /**
         * Fetches forms from cache up to the given step (and not after)
         * @param {Array} steps all steps in sequential order
         * @param {String} stepId the current step
         * @return {Array} flattened list of all forms up to given step
         */
        this.getFormsForStep = function (steps, stepId) {
            var forms = [];

            if (stepId !== '__startform') {
                // check start for start form
                forms.push(_getFormForStep('__startform'));

                if (stepId && steps && steps.length > 0) {
                    for (var i = 0; i < steps.length; i++) {
                        if (steps[i].id != stepId) {
                            forms.push(_getFormForStep(steps[i].id));
                        } else {
                            break;
                        }
                    }
                }
            }

            // only unique forms
            var uniqueIds = [];
            var uniqueForms = [];

            forms.forEach(function (item) {
                if (item && item.id) {
                    if (uniqueIds.indexOf(item.id) < 0) {
                        uniqueIds.push(item.id);
                        uniqueForms.push(item);
                    }
                }
            });

            uniqueForms.sort(function(a,b){
                return a.name.toLowerCase() > b.name.toLowerCase() ? 1 : -1;
            });

            return uniqueForms;
        };

        /**
         * Fetches form outcomes from cache for specific form
         * @param {String} formId
         * @return {Array} flattened list of all form outcomes
         */
        this.getFormOutcomesForForm = function (formId) {
            var outcomes = [];
            if (formId) {
                outcomes = _getFormOutcomesForForm(formId);
            }

            outcomes.sort(function(a,b){
                return a.name.toLowerCase() > b.name.toLowerCase() ? 1 : -1;
            });

            return outcomes;
        };

        /**
         * Fetches form fields from cache for specific form
         * @param {String} formId
         * @return {Array} flattened list of all form form fields
         */
        this.getFormFieldsForForm = function (formId) {
            var formFields = [];
            if (formId) {
                formFields = _getFormFieldsForForm(formId);
            }
            return formFields;
        };

        var _updateFormCache = function (stepId, formId) {
            if (stepId && formId) {
                $http({method: 'GET', url: FLOWABLE.APP_URL.getFormModelUrl(formId)}).
                    success(function(response) {
                        if (response) {
                            var outcomes;
                            var formFields;
                            if (response.formDefinition) {
                                if (response.formDefinition.fields) {
                                    formFields = response.formDefinition.fields;
                                }

                                if (response.formDefinition.outcomes) {
                                    outcomes = response.formDefinition.outcomes;
                                }
                            }
                            var filteredFormFields = _filterFormFields(formFields);
                            var formFieldInfo = {id: response.id, name: response.name, description: response.description, outcomes: outcomes, fields: filteredFormFields};
                            _addFormFieldsForStepToCache(stepId, formFieldInfo);
                        }
                    });
            }
            if (stepId && !formId) {
                _deleteFormFieldsForStepFromCache(stepId);
            }
        };

        var _getFormDefinitions = function (formIds, callback) {

            if (formIds.length > 0) {

                var formIdParams = '';
                for (var i = 0; i < formIds.length; i++) {
                    if (formIdParams.length > 0) {
                        formIdParams += '&';
                    }
                    formIdParams += 'formId=' + formIds[i];
                }
                if (formIdParams.length > 0) {
                    formIdParams += '&';
                }
                formIdParams += 'version=' + Date.now();

                $http({method: 'GET', url: FLOWABLE.APP_URL.getFormModelValuesUrl(formIdParams)}).
                    success(function (data) {
                        if (callback) {
                            callback(data);
                        }
                    }).

                    error(function (data) {
                        console.log('Something went wrong when fetching form values:' + JSON.stringify(data));
                    });
            }
        };
    }
]);
