import ngModule from '../module';
import {validateAll} from '../lib/validator';
import {firstUpper} from '../lib/string';

directive.$inject = ['$interpolate', '$compile', '$translate', '$window'];
export function directive(interpolate, compile, $translate, $window) {
    return {
        restrict: 'A',
        require: ['ngModel', '^^?form'],
        link: link
    };

    function link(scope, element, attrs, ctrl) {
        let vnValidations = $window.validations;

        if (!attrs.vnValidation || !vnValidations)
            return;

        let split = attrs.vnValidation.split('.');

        if (split.length !== 2)
            throw new Error(`vnValidation: Attribute must have this syntax: [entity].[field]`);

        let entityName = firstUpper(split[0]);
        let fieldName = split[1];
        let entity = vnValidations[entityName];

        if (!entity)
            throw new Error(`vnValidation: Entity '${entityName}' doesn't exist`);

        let validations = entity.validations[fieldName];
        if (!validations || validations.length == 0)
            return;

        let ngModel = ctrl[0];
        let form = ctrl[1];
        let errorSpan = angular.element('<span class="mdl-textfield__error"></span>');
        let errorMsg;
        let errorShown = false;

        ngModel.$options.$$options.allowInvalid = true;
        ngModel.$validators.entity = value => {
            try {
                validateAll($translate, value, validations);
                return true;
            } catch (e) {
                errorMsg = e.message;
                if (errorShown) changeError();
                return false;
            }
        };

        scope.$watch(() => {
            return (form.$submitted || ngModel.$dirty) && ngModel.$invalid;
        }, value => {
            let parent = element.parent();

            if (value) {
                changeError();
                parent.addClass('invalid');
                element.after(errorSpan);
            } else if (errorShown) {
                parent.removeClass('invalid');
                parent.removeAttr('title');
                errorSpan.remove();
                errorSpan.empty();
            }

            errorShown = value;
        });

        function changeError() {
            let parent = element.parent();
            errorSpan.text(errorMsg);
            parent.attr('title', errorMsg);
        }
    }
}
ngModule.directive('vnValidation', directive);