// web service proxy for spreadjs display
webservices.factory('spreadJsService', ['$log', '$q', '$http', 'apiConfig', 'documentHierarchyService',
    function ($log, $q, $http, apiConfig, documentHierarchyService) {
        'use strict';

        var formulaValues;
        var editingText;

        var getJsonFromExcel = function (filepath) {
            return $http.post('/spreadjs/getjson', { documentpath: filepath }, apiConfig.create());
        };

        var exportExcel = function (jsonContent) {
            return $http.post('/spreadjs/exportExcel', { jsonContent: jsonContent, fileType: 'application/json' }, apiConfig.create());
        };

        var getFormulaValueByDocumentId = function (documentId) {
            return $http.get('/spreadjs/formulavalue/' + documentId, apiConfig.create());
        };

        //通过公式列表获取公式值
        var getFormulaValueByFormulaList = function (formulaList) {
            var deferred = $q.defer();
            var promise = deferred.promise;
            $http.get('/spreadjs/formulavaluebyformula/' + JSON.stringify(formulaList), apiConfig.create())
                 .success(function (data) {
                     deferred.resolve(data);
                 })
                  .error(function (error) {
                      deferred.reject(error);
                  });
            return promise;
        };

        //通过文件code获取公式值
        var getFormulaValueByDocumentCode = function (code) {
            var deferred = $q.defer();
            var promise = deferred.promise;
            $http.get('/spreadjs/formulavaluebycode/' + code, apiConfig.create())
                 .success(function (data) {
                     deferred.resolve(data);
                 })
                  .error(function (error) {
                      deferred.reject(error);
                  });
            return promise;
        };

        //通过文件名获取公式值
        //ND(-1): 999, BB("CL027",2,5,2,0,0): 888, QR("1471",-1): 100, QR("1471",0): 100, QR("1471",1): 100
        var getFormulaValueByFileName = function (filepath) {
            var deferred = $q.defer();
            var promise = deferred.promise;

            $http.get('/spreadjs/formulavalue/' + filepath, apiConfig.create())
                    .success(function (data) {
                        deferred.resolve(data);
                    })
                    .error(function (error) {
                        deferred.reject(error);
                    });
            return promise;
        };

        var getDocumentCell = function (filepath) {
            return $http.get('/documentcell/byname/' + filepath, apiConfig.create());
        };

        var getDocumentCellByDocumentId = function (documentId) {
            return $http.get('/documentcell/byid/' + documentId, apiConfig.create());
        };

        var getCustomFunctions = function () {
            return $http.get('/spreadjs/customfunction', apiConfig.create());
        };

        var renderFormulaCell = function (sheet, celllist) {
            $.each(celllist, function (n, val) {
                var cIndex = val.columnIndex;
                var rIndex = val.rowIndex;
                var formula = val.formula;

                sheet.setFormula(rIndex, cIndex, "=" + formula);
                sheet.setTag(rIndex, cIndex, "=" + formula);
            })
        };

        var initSpreadCustomFunction = function (sheet, name, minArgs, maxArgs) {

            var customFunction = function (name, minArgs, maxArgs) {
                this.name = name;
                this.maxArgs = maxArgs;
                this.minArgs = minArgs;
            };

            customFunction.prototype = new GcSpread.Sheets.Calc.Functions.Function();
            customFunction.prototype.evaluate = function (args) {

                var formulaName = this.name + "(";

                for (var j = 0; j < args.length; j++) {
                    if (j < args.length - 1) {
                        formulaName += args[j].toString()
                        .replace("\"", "")
                        .replace("\"", "")
                        .replace(" ", "") + ",";
                    }
                    else {
                        formulaName += args[j].toString()
                        .replace("\"", "")
                        .replace("\"", "")
                        .replace(" ", "");
                    }
                }
                formulaName += ")";

                var value = formulaValues['' + formulaName + ''];
                return value;

            };

            var cf = new customFunction(name, minArgs, maxArgs);
            sheet.addCustomFunction(cf);
        };

        var initSpreadExcel = function (id, ssjsondata) {

            var deferred = $q.defer();
            var promise = deferred.promise;

            var spread = new GcSpread.Sheets.Spread(document.getElementById(id));
            var sheet = spread.getActiveSheet();

            spread.showVerticalScrollbar(true);
            spread.showHorizontalScrollbar(true);
            spread.tabNavigationVisible(false);
            spread.tabStripVisible(false);
            spread.newTabVisible(false);

            spread.isPaintSuspended(true);
            spread.fromJSON(JSON.parse(ssjsondata));
            spread.isPaintSuspended(false);

            sheet = spread.getActiveSheet();

            if (sheet != null) {
                sheet.setRowHeaderVisible(true);
                sheet.setColumnHeaderVisible(true);
                sheet.setIsProtected(false);
            }

            spread.bind(GcSpread.Sheets.Events.CellClick, function (sender, args) {
                if (args.sheetArea === GcSpread.Sheets.SheetArea.colHeader) {
                    $log.debug("The column header was clicked.");
                }

                if (args.sheetArea === GcSpread.Sheets.SheetArea.rowHeader) {
                    $log.debug("The row header was clicked.");
                }

                if (args.sheetArea === GcSpread.Sheets.SheetArea.corner) {
                    $log.debug("The corner header was clicked.");
                }

                $log.debug("cIndex: " + args.col);
                $log.debug("rIndex: " + args.row);
                $log.debug(sheet.getTag(args.row, args.col));
            });

            spread.bind(GcSpread.Sheets.Events.EditEnding, function (sender, args) {

                var sheet = spread.getActiveSheet();

                editingText = args.editingText;
                var reg = new RegExp('[a-zA-Z]+[\((]([0-9a-zA-Z,"".]|(-)?)*[\))]');
                var res = reg.test(editingText);

                if (res) {
                    var name = editingText.substring(1, editingText.indexOf("("));
                    $log.debug(name);
                    initSpreadCustomFunctionAsync(sheet, name);
                }
            });

            deferred.resolve(spread);
            return promise;
        };

        var renderSpreadExcelSimple = function (id, filepath) {

            var deferred = $q.defer();
            var promise = deferred.promise;

            getJsonFromExcel(filepath).then(function (ssjson) {
                //4. 加载SpreadExcel
                initSpreadExcel(id, ssjson.data).then(function (spread) {
                    deferred.resolve(spread);
                });
            });
            return promise;
        };

        /**
         * 通过document code获取该code下对应的公式以及公式的值
         * @method renderSpreadExcelFormulaByCode
         * @for 所属类名
         * @param {string} id   spreadjs div的id
         * @param {string} code document code,该code在 CIT_DocumentHierarchy中查到
         * @return {spread} 返回spread的对象
         */
        var renderSpreadExcelFormulaByCode = function (id, code) {

            var customfunctions;

            //1. 获取自定义函数名及对应的计算值
            getFormulaValueByDocumentCode(code).then(function (formuladata) {
                formulaValues = JSON.parse(formuladata);
                $log.debug(formulaValues);

                //2. 获取自定义函数名
                getCustomFunctions().then(function (functiondata) {
                    customfunctions = functiondata.data;

                    //通过code获取document filepath
                    documentHierarchyService.getDocumentByCode(code).success(function (documentObj) {
                        //3. 获取Excel的ssjon
                        getJsonFromExcel(documentObj.documentPath).then(function (ssjson) {
                            //4. 加载SpreadExcel
                            initSpreadExcel(id, ssjson.data).then(function (spread) {
                                //4. 初始化自定义函数名
                                var sheet = spread.getActiveSheet();
                                for (var i = 0; i < customfunctions.length; i++) {
                                    var func = customfunctions[i];
                                    initSpreadCustomFunction(sheet, func.name, 0, func.parameterCount);
                                }

                                //5. Get Document Cell
                                getDocumentCellByDocumentId(documentObj.documentID).then(function (celldata) {
                                    renderFormulaCell(sheet, celldata.data);
                                });
                            });
                        });
                    });
                });
            });
        };

        //最开始设计的版本
        var renderSpreadExcelFormula = function (id, documentName) {

            var customfunctions;

            //1. 获取自定义函数名及对应的计算值
            getFormulaValueByFileName(documentName).then(function (formuladata) {
                formulaValues = JSON.parse(formuladata);
                $log.debug(formulaValues);

                //2. 获取自定义函数名
                getCustomFunctions().then(function (functiondata) {
                    customfunctions = functiondata.data;

                    //3. 获取Excel的ssjon
                    getJsonFromExcel(documentName).then(function (ssjson) {
                        //4. 加载SpreadExcel
                        initSpreadExcel(id, ssjson.data).then(function (spread) {
                            //4. 初始化自定义函数名
                            var sheet = spread.getActiveSheet();
                            for (var i = 0; i < customfunctions.length; i++) {
                                var func = customfunctions[i];
                                initSpreadCustomFunction(sheet, func.name, 0, func.parameterCount);
                            }

                            //5. Get Document Cell
                            getDocumentCell(documentName).then(function (celldata) {
                                renderFormulaCell(sheet, celldata.data);
                            });
                        });
                    });
                });
            });
        };





        var initSpreadCustomFunctionAsync = function (sheet, name) {

            var asum = function () { }
            //Define a class "ASUM" that extends AsyncFunction
            asum.prototype = new GcSpread.Sheets.Calc.Functions.AsyncFunction(name, 1, 255);
            //Set default value to "Loading..."
            asum.prototype.defaultValue = function () { return "Loading..."; };
            //Override the evaluateAsync function
            asum.prototype.evaluateAsync = function (args, context) {

                var formulaName = this.name + "(";

                for (var j = 0; j < args.length; j++) {
                    if (j < args.length - 1) {
                        formulaName += args[j].toString()
                        .replace("\"", "")
                        .replace("\"", "")
                        .replace(" ", "") + ",";
                    }
                    else {
                        formulaName += args[j].toString()
                        .replace("\"", "")
                        .replace("\"", "")
                        .replace(" ", "");
                    }
                }
                formulaName += ")";
                var value = formulaValues['' + formulaName + ''];
                if (value === undefined) {

                    var formula = editingText.replace('=', '');
                    var formulaList = [formula];
                    //从服务端获取数据
                    getFormulaValueByFormulaList(formulaList).then(function (formuladata) {
                        var data = JSON.parse(formuladata);
                        //添加到全局formulaValues对象中
                        formulaValues[formula] = data[formula];

                        $log.debug(formulaValues);
                        var result = formulaValues['' + formulaName + ''];
                        context.SetAsyncResult(result);
                    });
                }
                return value;
            };

            var cf = new asum();
            sheet.addCustomFunction(cf);
        };






        return {
            getJsonFromExcel: getJsonFromExcel,
            exportExcel: exportExcel,
            getFormulaValueByDocumentId: getFormulaValueByDocumentId,
            getFormulaValueByFileName: getFormulaValueByFileName,
            getDocumentCell: getDocumentCell,
            getCustomFunctions: getCustomFunctions,
            initSpreadCustomFunction: initSpreadCustomFunction,
            initSpreadExcel: initSpreadExcel,
            renderFormulaCell: renderFormulaCell,
            renderSpreadExcelSimple: renderSpreadExcelSimple,
            renderSpreadExcelFormula: renderSpreadExcelFormula,
            renderSpreadExcelFormulaByCode: renderSpreadExcelFormulaByCode
        };
    }]);