'use strict';

var RecipeListController = ['$scope', 'recipes', '$location', '$routeParams', '$filter', 'Tokenizer', function ($scope, recipes, $location, $routeParams, $filter, Tokenizer) {
    $scope.info = recipes;
    $scope.search = $routeParams.q || '';
    $scope.product_groups = _.reduce(recipes, function (acculumator, item) {
        if (!acculumator.includes(item.ProductGroup)){
            acculumator.push(item.ProductGroup);
        }
        return acculumator;
    },[]).sort();

    $scope.startDate = function (startDate) {
        if (arguments.length === 0) {
            return $scope._startDate;
        }
        $scope._startDate = startDate;
        var re = /(('[s]'|"[s]"|[s]+)\s*:\s*('[^']+'|"[^"]+"|[^\s]+))/gi,
            matches = $scope.search.match(re),
            st = startDate === null ? '' : 's:>=' + moment(startDate).format('DD-MMM-YYYY');
        $scope.search = (matches === null) ? $scope.search.trim() + ' ' + st : $scope.search.replace(re, st);
    };

    $scope.finishDate = function (finishDate) {
        if (arguments.length === 0) {
            return $scope._finishDate;
        }
        $scope._finishDate = finishDate;
        var re = /(('[f]'|"[f]"|[f]+)\s*:\s*('[^']+'|"[^"]+"|[^\s]+))/gi,
            matches = $scope.search.match(re),
            st = finishDate === null ? '' : 'f:<=' + moment(finishDate).format('DD-MMM-YYYY');
        $scope.search = (matches === null) ? $scope.search.trim() + ' ' + st : $scope.search.replace(re, st);
    };

    $scope.productGroup = function (productGroup) {
        if (arguments.length === 0) {

            return $scope._productGroup;
        }
        $scope._productGroup = productGroup;
        var re = /(('[t]'|"[t]"|[t]+)\s*:\s*('[^']+'|"[^"]+"|[^\s]+))/gi,
            matches = $scope.search.match(re),
            st = 't:"' + productGroup + '"',
            search = (matches === null) ? $scope.search.trim() + ' ' + st : $scope.search.replace(re, st);
        $scope.search = search.trim();
    };

    $scope.$watch('search', function (value) {
        $scope.filterRecipes(value);
    }, true);

    $scope.$on('$destroy', function () {
        Tokenizer.doFilter.cache = {};
    });

    $scope.searchInfo = {
        comparator: {
            'n': {'Col': 'Name', 'Comparator': 'text'},
            't': {'Col': 'ProductGroup', 'Comparator': 'text'},
            's': {'Col': 'Prices.ValidFrom', 'Comparator': 'date'},
            'f': {'Col': 'Prices.ValidTo', 'Comparator': 'date'}
        },
        def: 'n',
        sorter: {
            'n': 'Name',
            't': 'ProductGroup',
            's': 'Prices.ValidFrom',
            'f': 'Prices.ValidTo',
            'c': 'Prices.Costing',
            'cp': 'Prices.CostPrice',
            'sp': 'Prices.SalePrice'
        },
        flags: {}
    };

    $scope.filterRecipes = _.debounce(function (q) {
        if (q !== $scope._search) {
            $scope._search = q;
            if (angular.isUndefined(q) || q === '') {
                $location.path('/Recipes').search('q', null).replace();
            } else {
                $location.path('/Recipes').search({'q': q}).replace();
            }
            $scope.$apply(function () {
                $scope.recipes = $scope.doFilter(q);
            });
        }
    }, 350);
    $scope.doFilter = _.memoize(function (q) {
        var matches = Tokenizer.parseFilterString(q, $scope.searchInfo),
            array = angular.copy($scope.info);

        array = $scope.subFilter(null, array, matches.q, matches.o);
        array.forEach(function (prod) {
            prod.Prices = $scope.subFilter('Prices.', prod.Prices, matches.q, matches.o);
        });
        return array;
    });

    $scope.subFilter = function (prefix, arr, q, o) {
        q = angular.copy(q);
        o = angular.copy(o);
        if (prefix === null) {
            q = q.filter(x => !x.Col.includes('.'));
            o = o.filter(x => !x.includes('.'));
        } else {
            q = q.filter(x => x.Col.startsWith(prefix));
            q.forEach(function (x) {x.Col = x.Col.substr(prefix.length)});
            o = o.filter(x => x.substr(1).startsWith(prefix)).map(x => x[0] + x.substr(prefix.length + 1));
        }
        if (q.length !== 0) {
            arr = arr.filter(item => q.every(exp => exp.Comparator(item[exp.Col], exp.Value)));
        }
        return $filter('orderBy')(arr, o);
    }
}];

RecipeListController.resolve = {
    recipes: ['Recipe', function (Recipe) {
        return Recipe.query({}).$promise;
    }]
};

var RecipeController = ['$scope', '$location', '$window', '$modal', 'asDateFilter', 'Product', 'recipe', function ($scope, $location, $window, $modal, asDate, Product, recipe) {
    recipe.ValidFrom = moment(recipe.ValidFrom, 'DD-MMM-YYYY').toDate();
    recipe.ValidTo = moment(recipe.ValidTo, 'DD-MMM-YYYY').toDate();
    $scope.recipe = recipe;
    $scope.foIngredient = recipe.RecipeItems > 0;

    $scope.costPrice = 0;
    function getOld(productID, recipeItems) {
        return _.find(recipeItems, function (recipe_item) {
            return recipe_item.Product.ProductID === productID;
        });
    }

    $scope.add = function () {
        if (!$scope.product || !$scope.product.ProductID || !$scope.quantity || Number(!$scope.quantity)) {
            return;
        }
        var oldItem = getOld($scope.product.ProductID, $scope.recipe.RecipeItems);
        if (angular.isUndefined(oldItem)) {
            var quantity = Number($scope.quantity);
            var price = Number($scope.product.Price);
            $scope.recipe.RecipeItems.push({
                Product: $scope.product,
                Quantity: quantity,
                Price: price
            });
        } else {
            $scope.toasts.push({Type: 'Danger', Message: 'Ingredient already in the list'});
        }
        delete $scope.quantity;
        delete $scope.product;
        $scope.searchIngredient = '';
        $scope.foIngredient = true;
    };

    $scope.removeItem = function (item) {
        var index = $scope.recipe.RecipeItems.indexOf(item);
        $scope.recipe.RecipeItems.splice(index, 1);
    };

    $scope.$watch('recipe.RecipeItems', function (recipeItems) {
        if (!angular.isArray(recipeItems)) {
            return;
        }
        $scope.costPrice = recipeItems.reduce(function (sum, item) {
            var rate = item.Price / (item.Product.Fraction * item.Product.ProductYield);
            return sum + (item.Quantity * rate);
        }, 0);
    }, true);

    $scope.save = function () {
        $scope.recipe.ValidFrom = asDate($scope.recipe.ValidFrom);
        if (angular.isUndefined($scope.recipe.ValidFrom) || $scope.recipe.ValidFrom === '') {
            $scope.toasts.push({Type: 'Danger', Message: 'Please Choose a proper validity period'});
            return;
        }
        $scope.recipe.ValidTo = asDate($scope.recipe.ValidTo);
        if (angular.isUndefined($scope.recipe.ValidTo) || $scope.recipe.ValidTo === '') {
            $scope.toasts.push({Type: 'Danger', Message: 'Please Choose a proper validity period'});
            return;
        }
        $scope.recipe.$save(function (u, putResponseHeaders) {
            $scope.toasts.push({Type: 'Success', Message: ''});
            $window.history.back();
        }, function (data, status) {
            $scope.toasts.push({Type: 'Danger', Message: data.data});
        });
    };

    $scope.delete = function () {
        $scope.recipe.$delete(function (u, putResponseHeaders) {
            $scope.toasts.push({Type: 'Success', Message: ''});
            $window.history.back();
        }, function (data, status) {
            $scope.toasts.push({Type: 'Danger', Message: data.data});
        });
    };

    $scope.confirm = function () {
        var modalInstance = $modal.open({
            backdrop: true,
            templateUrl: '/template/modal/confirm.html',
            controller: ['$scope', '$modalInstance', function ($scope, $modalInstance) {
                $scope.title = "Delete Recipe";
                $scope.body = "Are you sure? This cannot be undone.";
                $scope.isDelete = true;
                $scope.ok = function () {
                    $modalInstance.close();
                };
                $scope.cancel = function () {
                    $modalInstance.dismiss('cancel');
                };
            }]
        });
        modalInstance.result.then(function () {
            $scope.delete();
        });
    };
    $scope.products = function ($viewValue, options) {
        return Product.autocomplete(angular.extend({
            term: $viewValue,
            count: 20,
            a: true,
            e: true
        }, options)).$promise;
    };


}];

RecipeController.resolve = {
    recipe: ['$route', 'Recipe', function ($route, Recipe) {
        var id = $route.current.params.id;

        return Recipe.get({id: id}).$promise;
    }]
};
