/**
 * Angular application of Digpedia extended to work as popup in a chrome extension
 * Require: action.js
 * @author Massimiliano Battan
 * @version 3.6
 * 
 **/

var resource;
var locale;


(function () {
    angular.element(document).ready(function () {
        chrome.tabs.query({active: true, lastFocusedWindow: true}, function (activeTabs) {
            var tabId = activeTabs[0].id;
            if (tabId != undefined) {
                chrome.storage.local.get(["name", "locale", "id"], function (data) {
                    resource = data.name;
                    locale = data.locale;
                    console.log("Resource:" + resource + ". Bootstrap AngularJS application.");
                    angular.bootstrap(document, ['findas']);

                });
            }
        });

    });

    var application = angular.module('findas', ['findasservices',
        'ui.grid', 'ui.grid.pagination',
        'ui.grid.resizeColumns',
        'ui.grid.autoResize',
        'ui.grid.exporter',
        'ui.grid.selection']).config([
        '$compileProvider', function ($compilerProvider) {
            $compilerProvider.imgSrcSanitizationWhitelist(/^\s*(chrome-extension):/); //this is mandatory for plugin for using img
            $compilerProvider.aHrefSanitizationWhitelist(/^.*/); //this is mandatory for plugin for using links (<a href)
        }
    ]);

    application.controller('PropertyController', ['propertyservice', '$scope', 'queryService', function (propertyservice, $scope, queryService) {
            this.resource = resource;
            //reflect WikiPageResultDTO
            this.params = {
                templates: [],
                categories: []
            };
            this.additionalprops = [];
            this.resultType = "nothing";

            this.services = {
                backend: true,
                dbpedia: true
            };

            this.parseResult = false;

            this.digpediaResult= false;
            this.dbpediaResult = false;
            this.supportedResult = true;
            /*
             * Advanced settings
             */
            this.maxresult = 50;
            this.includers = false;
            this.selectedCat = undefined;
            this.orderby = undefined;
            this.orders = [];

            //grid to display the result. Set some default settings
            this.gridResultOptions = {
                enableSorting: true,
                enableGridMenu: true,
                enableColumnResizing: true,
                paginationPageSizes: [25, 50, 200],
                paginationPageSize: 25,
                exporterPdfCustomFormatter: function (docDefinition) {
                    docDefinition.pageMargins = [40, 60, 40, 60];
                    docDefinition.styles.footerStyle = {bold: true, fontSize: 8};
                    docDefinition.styles.headerStyle = {fontSize: 16, bold: true};
                    return docDefinition;
                },
                exporterPdfDefaultStyle: {fontSize: 9},
                exporterPdfOrientation: 'landscape',
                exporterPdfTableHeaderStyle: {fontSize: 10, bold: true, italics: false, color: 'blue'},
                exporterPdfTableStyle: {margin: [10, 10, 10, 10]},
            };

            /**
             * DBPEDIACATEGORIESDTO
             */
            this.innerClass = {};
            this.dbpediaClasses = [];

            chrome.storage.local.get(["include_rs", "maxresult"], angular.bind(this, function (data) {
                //get settings if any
                if (data.maxresult != undefined) {
                    this.maxresult = data.maxresult;
                    $('#green').slider('option', 'value', this.maxresult);
                }
                if (data.include_rs != undefined) {
                    this.includers = data.include_rs;
                }
            }));
            /*
             * save setting on change
             */
            this.saveincludeRs = function () {
                var item = {"include_rs": this.includers};
                chrome.storage.local.set(item, function () {

                });
            }
            /*
             * save setting on change
             */
            this.savemaxResult = function () {
                var item = {"maxresult": this.maxresult};
                chrome.storage.local.set(item, function () {

                });
            }
            queryService.queryDbpediaInner().get({},
                    angular.bind(this, function (data) {
                        console.log(data.$httpstatus);
                        if (data.$httpstatus == 200) {
                            this.dbpediaClasses = data.categories.others;
                            this.innerClass = this.dbpediaClasses[0];
                            this.dbpediaResult = true;
                        } else{
                            this.supportedResult = false;
                        }
                    }),
                    angular.bind(this, function () {
                        this.services.dbpedia = false;
                    })
                    );

            this.showDialog = function ($event, data) {
                showDialog($event.target, data);
            };

            this.clickSingleDate = function (key, value, param) {
                param.value = "";
                var hasyear = hasYear(value);
                clickSingleDate(key, hasyear);
            };

            this.clickRangeDate = function (key, value, param) {
                param.value = "[,]";
                param.type = "=";
                var hasyear = hasYear(value);
                clickRangeDate(key, hasyear);
            };

            this.clickSingleDigit = function (key, value, param) {
                param.value = 0;
                var steps = [];
                steps = getSteps(value);
                clickSingleDigit(key, steps);
            };

            this.clickRangeDigit = function (key, value, param) {
                param.type = "=";
                var steps = [];
                steps = getSteps(value);
                param.value = "[" + steps[3] + "," + steps[4] + "]";
                clickRangeDigit(key, steps);
            };

            this.showHiddenInfo = function (el) {
                showHiddenInfo(el);
            };

            this.changeIcon = function (id, value) {
                var imgurl;
                switch (value) {
                    case "starts with":
                        imgurl = "sw";
                        break;
                    case "equals":
                        imgurl = "equal";
                        break;
                    case "=":
                        imgurl = "equals";
                        break;
                    case "ends with":
                        imgurl = "ew";
                        break;
                    case "contains":
                        imgurl = "co";
                        break;
                    case "<":
                        imgurl = "lt";
                        break;
                    case ">":
                        imgurl = "gt";
                        break;
                    case "≤":
                        imgurl = "le";
                        break;
                    case "≥":
                        imgurl = "ge";
                        break;
                }
                var input = $("[id='input" + id + "']");
                input.css("background-image", "url('js/img/" + imgurl + ".png')");
            }

            /*
             * Call backend parser to init properties
             */
            propertyservice.getProperty({},
                    angular.bind(this, function (data) {
                        if (data.Res != undefined) {
                            var params = {
                                templates: [],
                                categories: data.Res.categories
                            };
                            angular.forEach(data.Res.templates, function (template, indexTemplate) {
                                params.templates[indexTemplate] = {
                                    temp: template.category,
                                    props: []};
                                var props = [];
                                angular.forEach(template.properties, function (prop, indexprop) {
                                    var alias;
                                    if (prop.key.label != undefined) {
                                        alias = prop.key.label;
                                    } else {
                                        alias = prop.key.rawKey;
                                    }
                                    var param = {
                                        name: prop.key.dbpediaKey,
                                        alias: alias,
                                        checked: false,
                                        value: prop.values[0].val,
                                        type: "=",
                                        valuetype: prop.values[0].type,
                                        selector: "nothing"
                                    };
                                    props.push(param);

                                }, this);
                                params.templates[indexTemplate].props = props;
                            }, this);
                            this.parseResult = true;
                            this.digpediaResult = true;
                            this.setValues(data, params);
                        } else{
                            this.supportedResult = false;
                        }
                    }),
                    angular.bind(this, function error(error) {
                        this.parseResult = true;
                        this.services.backend = false;
                    })
                    );

            this.inject = function (data, params) {
                $scope.$evalAsync(this.setValues(data, params));
            };

            this.setValues = function (data, params) {
                this.setParams(params);
                this.setProperties(data);
            };

            this.setParams = function (data) {
                this.params = data;
            };

            this.setProperties = function (data) {
                this.properties = data;
            };

            /*
             * Query function
             * Includes settings 
             */
            this.query = function () {
                collapseAll();
                this.resultType = "nothing";
                this.results = [];
                var q = {"query":
                            {"params": [],
                                "settings": {
                                    "limit": this.maxresult,
                                    "includers": this.includers,
                                    "orderby": this.orderby
                                },
                                "wikiCategory": this.selectedCat,
                                "category": {
                                    "label": this.innerClass.label,
                                    "categoryname": this.innerClass.categoryname,
                                    "code": this.innerClass.code
                                }
                            }
                };
                angular.forEach(this.additionalprops, function (addProp) {
                    if (addProp.checked) {
                        var queryParam = {
                            "value": addProp.value,
                            "property": addProp.name,
                            "typeParam": addProp.type,
                            "type": "",
                            "alias": addProp.name
                        };
                        q.query.params.push(queryParam);
                    }
                }, this);
                angular.forEach(this.params.templates, function (template, indexTemp) {
                    angular.forEach(template.props, function (prop, indexProp) {
                        if (prop.checked) {
                            var optRef = this.lookUpRefString(prop.value, indexProp, indexTemp);
                            if (optRef != undefined) {
                                console.log(optRef);
                                var queryParam = {
                                    "value": prop.value,
                                    "property": prop.name,
                                    "typeParam": prop.type,
                                    "type": prop.valuetype,
                                    "optionalRef": optRef,
                                    "alias": prop.alias};
                            } else {
                                var queryParam = {
                                    "value": prop.value,
                                    "property": prop.name,
                                    "typeParam": prop.type,
                                    "type": prop.valuetype,
                                    "alias": prop.alias};
                            }
                            //console.log(queryParam);
                            q.query.params.push(queryParam);
                        }
                    }, this);
                }, this);
                //console.log(q);

                queryService.getQueryResult().post({}, q, angular.bind(this, function (data) {
                    //When I get a result, destroy the modla dialog
                    $("#modal_wait").dialog("destroy");
                    if (data.$httpstatus == 200) {
                        //console.log(data.result.rows);
                        this.resultType = "valid";
                        //create each time a new column model
                        var columns = [];
                        angular.forEach(data.result.columns, function (column) {
                            if (column.name == 'DBpedia_page') {
                                columns.push({
                                    name: column.name,
                                    field: 'row.' + column.name,
                                    displayName: column.displayName,
                                    cellTemplate: '<div class="ui-grid-cell-contents centeredCol"><a href="{{COL_FIELD}}" target="_blank" title="Link to DBpedia resource page"><img src="js/img/dbpedia_logo.png" style="width: 40px;height: 25px;"/></a></div>',
                                    width: 120,
                                    enableColumnResizing: false});
                            } else if (column.name == 'Wikipedia_page') {
                                columns.push({
                                    name: column.name,
                                    field: 'row.' + column.name,
                                    displayName: column.displayName,
                                    cellTemplate: '<div class="ui-grid-cell-contents centeredCol"><a href="{{COL_FIELD}}" target="_blank" title="Link to Wikipedia article" ><img style="width:28px;height:25px" src="js/img/wikipedia-icon.jpg"/></a></div>',
                                    width: 150,
                                    enableColumnResizing: false});
                            } else {
                                columns.push({
                                    name: column.name,
                                    field: 'row.' + column.name,
                                    displayName: column.displayName});
                            }

                        }, this);

                        //inject columns,data and other option in the grid option object
                        this.gridResultOptions.columnDefs = columns;
                        this.gridResultOptions.data = data.result.rows;
                        this.gridResultOptions.exporterPdfHeader = {text: "Result for query:...", style: 'headerStyle', margin: 10};
                        this.gridResultOptions.exporterCsvFilename = "DigpediaResult.csv";
                        this.gridResultOptions.exporterPdfFooter = {
                            columns: [
                                'Results:' + data.result.rows.length,
                                {text: 'Digpedia export (3.1)', style: 'footerStyle', alignment: 'right'}],
                            margin: [5, 20, 5, 0]
                        }
                    } else {
                        this.resultType = "empty";
                    }

                }), angular.bind(this, function (error) {
                    $("#modal_wait").dialog("destroy");
                    if (error.status == 502) {
                        this.resultType = "invalid";
                        this.services.dbpedia = false;
                    } else if (error.status == 400) {
                        this.resultType = "invalid";
                        this.services.dbpedia = false;
                    } else {
                        this.resultType = "invalid";
                        this.services.dbpedia = false;
                    }

                })
                        );

            };

            this.addNewProperty = function () {
                var property = {checked: true, value: "", name: "", type: "="};
                this.additionalprops.push(property);
            };

            this.removeAll = function () {
                this.additionalprops = [];
            };

            this.removeProperty = function () {
                angular.forEach(this.additionalprops, function (data, index) {
                    //console.log(data);
                    if (data.checked) {
                        //console.log(index);
                        this.additionalprops.splice(index, 1);
                    }
                }, this);
            };

            this.lookUpRefString = function (propValue, propIndex, templateIndex) {
                var result = undefined;
                var javaProp = this.properties.Res.templates[templateIndex].properties[propIndex];
                if (javaProp != undefined) {
                    angular.forEach(javaProp.values, function (value) {
                        if (value.val == propValue) {
                            result = value.ref;
                        }
                    });
                }
                return result;
            };

            this.changeOrderBy = function (event, el) {
                var cb = $(event.target);
                var val = el.prop.key.label == null ? el.prop.key.rawKey : el.prop.key.label;
                var order = {label: val,
                    dbpedia: el.prop.key.dbpediaKey};
                if (cb.is(":checked")) {
                    this.orders.push(order);
                } else {
                    angular.forEach(this.orders, function (order, index) {
                        if (order.label == val) {
                            this.orders.splice(index, 1);
                            return;
                        }
                    }, this);
                }
            }

        }]);

    application.controller('AdditionalController', ['queryService', function (queryService) {
            this.gotdbpedia = false;
            this.dbpediaprops = [];
            this.selected = {};


            this.setSelected = function (prop) {
                this.selected = prop.name;
            };

            this.getValuesForSelected = function () {
                var values = [];
                angular.forEach(this.dbpediaprops, function (data) {
                    if (data.name == this.selected) {
                        values = data.values;
                        return;
                    }
                }, this);
                return values;
            };

            this.fetchDbpediapProp = function () {
                queryService.queryDbpediaProps().getDbpedia({}, angular.bind(this, function (data) {
                    this.dbpediaprops = data.Result.properties;
                    this.gotdbpedia = true;
                }), function () {

                });
            };

        }]);

    application.directive('prova', function () {
        return function (scope, element, attr) {
            var uniqueId = attr.prova;

            var childs = element.children();

            scope.$watch('wikiprops.properties', function (newVal, oldVal, scope) {
                if (newVal !== undefined) {
                    element.attr("id", uniqueId + "radio");
                    angular.element(childs[0]).attr("id", uniqueId + "single");
                    angular.element(childs[1]).attr("for", uniqueId + "single");
                    angular.element(childs[2]).attr("id", uniqueId + "range");
                    angular.element(childs[3]).attr("for", uniqueId + "range");
                    initButton(uniqueId + "radio");
                }

            });
        };
    });

    application.directive('opendrop', function () {
        return function (scope, el, attr) {
            el.on('click', function () {
                showDrop(el);
            });
        };
    });

    application.directive('sliderres', function () {
        return {
            restrict: "A",
            require: 'ngModel',
            link: function (scope, element, attrs, ngModelCtrl) {

                $('#green').slider({
                    orientation: "horizontal",
                    max: 9999,
                    min: 0,
                    range: "min",
                    value: 0,
                    step: 50,
                    slide: function (event, ui) {
                        //bind the slide fuction of jquery to the model update of angular
                        ngModelCtrl.$setViewValue(ui.value);
                        ngModelCtrl.$render();
                    }
                });

                scope.$watch("wikiprops.maxresult", function (newValue, oldValue) {
                    if (newValue == oldValue) {
                        //on the application init, set the slider to the current value for maxresult
                        $('#green').slider("option", "value", newValue);
                    }
                });
            }
        };
    });

})();

function initButton(id) {
    if ($.fn.button.noConflict) {
        $.fn.btn = $.fn.button.noConflict();
    }
    var element = $("[id='" + id + "']");
    element.buttonset();

}


  