/* Minification failed. Returning unminified contents.
(1,1): run-time error CSS1019: Unexpected token, found '('
(1,11): run-time error CSS1031: Expected selector, found '('
(1,11): run-time error CSS1025: Expected comma or open brace, found '('
(1889,2): run-time error CSS1019: Unexpected token, found '('
(1889,3): run-time error CSS1019: Unexpected token, found ')'
(1889,4): run-time error CSS1019: Unexpected token, found ')'
(1898,9): run-time error CSS1030: Expected identifier, found 'module('
(1898,9): run-time error CSS1031: Expected selector, found 'module('
(1898,9): run-time error CSS1025: Expected comma or open brace, found 'module('
 */
(function () {
    // define your controller and its logic in a local function variable
    var signupController = function ($scope, $state, $sce, ModalConfirmService, CallApi, CallRestApi, $http, ServerValues) {
        // we will store all of our form data in this object
        $scope.formData = { form: 'profile', countryCode: '+47' };
        $scope.me = null;
        $scope.showNavigation = true;
        $scope.familiyScreen = { form: 'selectPersons' };
        $scope.newRelation = {};
        $scope.organizationID = ServerValues.organizationID;
        $scope.organizationName = ServerValues.organizationName;
        $scope.redirectUrl = ServerValues.redirectUrl;
        $scope.existingPersons = [];
        $scope.currentState = null;
        $scope.currentStepIdx = -1;
        $scope.organizationTree = [];
        $scope.subOrganizations = [];
        $scope.selectablePriceItems = [];
        $scope.countryCodes = [];
        $scope.countries = [];
        $scope.memberships = [];
        $scope.personOrg = null;
        $scope.saving = false;
        $scope.debugMode = false;
        $scope.membershipPayers = [];
        $scope.attributes = null;
        $scope.showSubOrgs = true;
        $scope.searching = false;
        $scope.requireSuborgSelection = false;
        $scope.enableDepartmentSelection = false; // PIL-2322. Changed to false. Not useful to get a role in department.
        $scope.enableGroupSelection = true;
        $scope.orderTotal = 0;        
        $scope.introMessage = "";
        $scope.signupToGroupID = parseInt(ServerValues.signupToGroupID);
        $scope.signupToGroupName = ServerValues.signupToGroupName;
        $scope.signupToGroupKey = ServerValues.signupToGroupKey;
        $scope.steps = [
            { name: 'Meg', route: 'form.profile', state: '.profile', enabled: true },
            { name: 'Personer', route: 'form.family', state: '.family', enabled: true }
        ];
        if (!Modernizr.inputtypes.date) {
            $scope.dateFormatHint = " (åååå-mm-dd)";
        }
        // Hide suborgs for BMW MC Klubb Norge
        if ($scope.organizationID == 4774) {
            $scope.showSubOrgs = false;
        }
        // Require that all members must select at least one suborg
        if ($scope.organizationID == 8260) { // Kongsberg IF
            $scope.requireSuborgSelection = true;
        }

        $scope.famChildrenCnt = 0;
        $scope.famAdultCnt = 0;
        $scope.famTotCnt = 0;

        $scope.socialnumberPattern = /^\d{11}$/;
        $scope.days = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31];
        $scope.months = [{ m: 0, c: "Januar" }, { m: 1, c: "Februar" }, { m: 2, c: "Mars" }, { m: 3, c: "April" }, { m: 4, c: "Mai" }, { m: 5, c: "Juni" }, { m: 6, c: "Juli" }, { m: 7, c: "August" }, { m: 8, c: "September" }, { m: 9, c: "Oktober" }, { m: 10, c: "November" }, { m: 11, c: "Desember" }];
        $scope.years = [];

        $scope.locale = 'no';
        var keys = [];
        keys['no'] = [];
        keys['no']['member'] = {
            profileDesc: 'Registrer dine persondata under',
            pFirstName: 'Fornavn og mellomnavn',
            cFirstName: 'Barnets fornavn og mellomnavn',
            pLastName: 'Etternavn',
            cLastName: 'Barnets etternavn',
            pEmail: 'Epost',
            pMobile: 'Mobil',
            pBirthDate: 'Fødselsdato',
            pGender: 'Kjønn',
            pSexM: 'Mann',
            pSexF: 'Kvinne',
            pSexNonB: 'Ikke-binær',
            pAddress: 'Adresse',
            pZipCode: 'Postnr',
            pCity: 'Sted',
            pSsn: 'Fødselsnummer (11 siffer)',
            pConsent: 'Jeg samtykker til at personopplysninger lagres i Rubic',
            pConsentDescription: 'Hva innebærer dette?'
        };
        keys['no']['child'] = {
            profileDesc: 'Når du som foresatt skal melde in ditt barn som medlem starter vi med å registrere dine persondata først (foresattes). Dette gjør vi slik at du kan opprette brukernavn/passord på din profil før den kobles til barnet som skal være medlem i neste steg. Du vil ikke bli medlem med mindre du velger det i de neste stegene',
            pFirstName: 'Ditt fornavn og mellomnavn',
            pLastName: 'Ditt etternavn',
        };
        $scope.trans = [];
        
        $scope.bmwUnderOrgIDs = [6305, 6451, 6452, 6453, 6454, 6455, 6456, 6462, 6463, 6464, 6582];

        var now = new Date();
        var year = now.getFullYear();
        var lastYear = 1900;
        while (year >= lastYear) {
            $scope.years.push(year);
            year--;
        }
        $scope.birthDate = {};
        $scope.relBirthDate = {};
        /*
        $scope.birthDate = { day: 0, month: 0, year: 0 };
        $scope.birthDate.day = $scope.formData.birthDate.getDate();
        $scope.birthDate.month = $scope.formData.birthDate.getMonth();
        $scope.birthDate.year = $scope.formData.birthDate.getFullYear();
        */

        $scope.onKeyPress = function ($event) {
            let charCode = String.fromCharCode($event.which).toLowerCase();
            if ($event.ctrlKey && charCode === 'q') {
                $scope.debugMode = !$scope.debugMode;
            }
        };

        $scope.setLocale = function () {
            $scope.trans = angular.copy(keys[$scope.locale]['member']);
            if ($scope.formData.mode != 'member') {
                for (var item in keys[$scope.locale][$scope.formData.mode]) {
                    $scope.trans[item] = keys[$scope.locale][$scope.formData.mode][item];
                }
            }
            //$scope.trans = keys[$scope.locale][$scope.formData.mode];
        }
        $scope.getOrganization = function () {
            CallApi(function () { return $http.get("/api/OrganizationsApi/GetSignupConfig/" + $scope.organizationID); })
                .then(function (org) {
                    $scope.organization = org;
                    if ($scope.organization.signupOurTermsCaption != null && $scope.organization.signupOurTermsCaption.length == 0) { $scope.organization.signupOurTermsCaption = "Bekreft våre betingelser"; }
                    if ($scope.organization.setupAndInvoiceMembership) $scope.steps.push({ name: 'Medlemskap', route: 'form.membership', state: '.membership', enabled: true });
                    if ($scope.organization.signupEnableSelectablePriceItems) $scope.steps.push({ name: 'Tillegg', route: 'form.additions', state: '.additions', enabled: true });
                    if ($scope.organization.signupEnableFieldsScreen) $scope.steps.push({ name: 'Spørsmål', route: 'form.fields', state: '.fields', enabled: true });                    
                    if ($scope.signupToGroupID > 0) {
                        $scope.steps.push({ name: $scope.signupToGroupName, route: 'form.group', state: '.group', enabled: true });
                    } else if ($scope.organization.signupEnableOrgunitsScreen) {
                        $scope.steps.push({ name: 'Grupper', route: 'form.org', state: '.org', enabled: true });
                    } 
                    if ($scope.organization.enableRankOnRoles) {
                        $scope.redirectUrl = '/Oslokolonihager#/ventelister';
                    }
                    if ($scope.organization.signupSelectMemberMode == false) {
                        $scope.formData.mode = "member";
                        $scope.setLocale();
                    }
                    if ($scope.organization.customerTypeID == 7) {                        
                        $scope.setLocale();
                    }
                    $scope.introMessage = $sce.trustAsHtml($scope.organization.signupIntroMessage);
                    if (ServerValues.personID != '') {
                        CallRestApi(function () { return $http.get("/rest/persons/" + ServerValues.personID + "?includeRoles=true") })
                            .then(function (person) {
                                $scope.formData = person;
                                $scope.formData.concent = true;
                                $scope.formData.validated = true;
                                $scope.formData.form = "profile";
                                $scope.formData.mode = "member";

                                $scope.showAddParentRelation = $scope.formData.children.length === 0;
                                $scope.showAddChildrenRelation = $scope.formData.parents.length === 0;
                                $scope.showAddOtherRelation = true;

                                // Validate who is member already
                                $scope.validateExistingMemberships();
                                
                                $scope.getOrgData();
                                $scope.setLocale();

                                $scope.vaidateFormData();
                                $scope.currentStepIdx = 1;
                                $state.go("form.family");
                                $scope.toggleSteps();
                            });
                    }
                }, function (error) {
                    showError(error.toString());
                });
        };
        $scope.getMe = function () {
            CallRestApi(function () { return $http.get("/rest/persons/me"); })
                .then(function (data) {
                    $scope.me = data;
                }, function (error) {
                    // Fail silently..
                    // User is not logged in
                });
        }

        if ($scope.organizationID) {
            $scope.getOrganization();
            $scope.getMe();
        }
        
        
        $scope.getCountries = function () {
            $http.get("/api/BasicDataApi/GetCountries")
                .success(function (data, status, headers, config) {
                    data.data.forEach(function (country) {
                        if (country.phoneCountryCode != '' && country.phoneCountryCode != 'null' && !isNaN(parseInt(country.phoneCountryCode))) {
                            country.countryCode = country.phoneCountryCode;
                            country.phoneCountryCode = '+' + country.phoneCountryCode;                            
                            $scope.countryCodes.push(country);
                        }
                        $scope.countries.push(country);
                    });
                    $scope.countryCodes.sort((a, b) => (a.phoneCountryCode > b.phoneCountryCode) ? 1 : -1);
                    $scope.countries.sort((a, b) => (a.countryName_en > b.countryName_en) ? 1 : -1);
                    $scope.formData.countryCode = '47';
                })
                .error(function (data, status, headers, config) {
                }
                );
        }
        $scope.getCountries();

        $scope.validateExistingMemberships = function () {            
            if ($scope.formData.roles.filter(r => r.organizationId == $scope.organizationID).length > 0) {
                $scope.formData.isAlreadyMember = true;
                $scope.formData.isMember = $scope.signupToGroupID > 0 ? false : true;
            }
            $scope.formData.children.forEach(function (child) {
                if (child.roles != null && child.roles.filter(r => r.organizationId == $scope.organizationID).length > 0) {
                    child.isAlreadyMember = true;
                    child.isMember = $scope.signupToGroupID > 0 ? false : true;
                }
            });
            $scope.formData.parents.forEach(function (parent) {
                if (parent.roles != null && parent.roles.filter(r => r.organizationId == $scope.organizationID).length > 0) {
                    parent.isAlreadyMember = true;
                    parent.isMember = $scope.signupToGroupID > 0 ? false : true;
                }
            });
            $scope.formData.otherFam.forEach(function (other) {
                if (other.roles != null && other.roles.filter(r => r.organizationId == $scope.organizationID).length > 0) {
                    other.isAlreadyMember = true;
                    other.isMember = $scope.signupToGroupID > 0 ? false : true;
                }
            });
        }

        $scope.selectPerson = function (personID) {
            var url = "/Account/Signup?organizationID=" + $scope.organizationID + "&personID=" + personID;
            if ($scope.signupToGroupKey != null && $scope.signupToGroupKey != "") {
                url += "&groupKey=" + $scope.signupToGroupKey;
            }
            
            window.location.href = url;
        }
        $scope.login = function () {
            window.location.href = "/Account/SignupVipps?organizationID=" + $scope.organizationID
        }

        $scope.next = function () {
            $scope.currentState = $state.current;
            var fromStep = $scope.getStep(0);
            var toStep = $scope.getStep(1);
            if (toStep != null && $scope.validateTransition(fromStep, toStep)) {
                $scope.currentStepIdx++;
                $state.go(toStep.route);
            }

        }

        $scope.back = function () {
            $scope.currentState = $state.current;
            var fromStep = $scope.getStep(0);
            var toStep = $scope.getStep(-1);
            if (toStep != null && $scope.validateTransition(fromStep, toStep)) {
                $scope.currentStepIdx--;
                $state.go(toStep.route);
            }
        }
        $scope.validateDate = function (dateObj) {
            var fullMonths = [0, 2, 4, 6, 7, 9, 11];

            if (!fullMonths.includes(parseInt(dateObj.month)) && dateObj.day > 30) {
                dateObj.day = 30;
            }
            if (parseInt(dateObj.month) == 1) {
                var febTreshold = ((dateObj.year % 4 == 0) && (dateObj.year % 100 != 0)) || (dateObj.year % 400 == 0) ? 29 : 28;
                if (dateObj.day > febTreshold) {
                    dateObj.day = febTreshold;
                }
            }
            return new Date(dateObj.year, dateObj.month, dateObj.day);
        }

        $scope.validateSocialnumber = function (nr) {
            $scope.isValidSocialnumber = $scope.checkValidSocialnumber(nr);
        }

        $scope.checkValidSocialnumber = function (nr) {
            if (!nr || nr.length != 11) {
                return false;
            }

            var day = nr.substr(0, 2);
            var month = nr.substr(2, 2);
            var year = nr.substr(4, 2);
            var ind = nr.substr(6, 3);
            var c1 = nr.substr(9, 1);
            var c2 = nr.substr(10, 1);
            var yearno = parseInt(year);

            if (ind > 0 && ind < 500) {
                yearno += 1900;
            } else if (ind > 499 && ind < 750 && year > 55 && year < 100) {
                yearno += 1800;
            } else if (ind > 499 && ind < 999 && year >= 00 && year < 40) {
                yearno += 2000;
            } else if (ind > 899 && ind < 999 && year > 39 && year < 100) {
                yearno += 1900;
            } else {
                return false;
            }
            var d1 = parseInt(day.substr(0, 1));
            var d2 = parseInt(day.substr(1, 1));
            var m1 = parseInt(month.substr(0, 1));
            var m2 = parseInt(month.substr(1, 1));
            var a1 = parseInt(year.substr(0, 1));
            var a2 = parseInt(year.substr(1, 1));
            var i1 = parseInt(ind.substr(0, 1));
            var i2 = parseInt(ind.substr(1, 1));
            var i3 = parseInt(ind.substr(2, 1));

            // Calculate control check c1
            var c1calc = 11 - (((3 * d1) + (7 * d2) + (6 * m1) + m2 + (8 * a1) + (9 * a2) + (4 * i1) + (5 * i2) + (2 * i3)) % 11);
            if (c1calc == 11)
                c1calc = 0;
            if (c1calc == 10) {
                return false;
            }
            if (c1 != c1calc) {
                return false;
            }

            // Calculate control check c2
            var c2calc = 11 - (((5 * d1) + (4 * d2) + (3 * m1) + (2 * m2) + (7 * a1) + (6 * a2) + (5 * i1) + (4 * i2) + (3 * i3) + (2 * c1calc)) % 11);
            if (c2calc == 11)
                c2calc = 0;
            if (c2calc == 10) {
                return false;
            }
            if (c2 != c2calc) {
                return false;
            }
            // If all checks are okay we can update birthdate and gender
            var gender = 'M';
            if (i3 % 2 == 0) gender = 'F';// if odd number the user is female. Otherwise male. 
            if ($scope.currentStepIdx === 0) {
                $scope.birthDate.day = parseInt(day);
                $scope.birthDate.month = parseInt(month - 1);
                $scope.birthDate.year = yearno;
                $scope.formData.gender = gender;
            }
            else {
                $scope.relBirthDate.day = parseInt(day);
                $scope.relBirthDate.month = parseInt(month - 1);
                $scope.relBirthDate.year = yearno;
                $scope.newRelation.gender = gender;
            }
            return true;
        }

        $scope.goto = function (toRoute) {
            $scope.currentState = $state.current;
            var fromStep = $scope.getStep(0);
            var toStep = null;

            if ($scope.validateTransition(fromStep, toStep)) {
                $scope.steps.forEach(function (step, idx) {
                    if (toRoute == step.route) {
                        toStep = step;
                        $scope.currentStepIdx = idx;
                    }
                });
                $state.go(toRoute);
            }


        }

        $scope.getStep = function (increment) {
            var currentStepIdx = $scope.getCurrentIdx();
            var nextStepIdx = currentStepIdx + increment;
            while (increment != 0 && typeof $scope.steps[nextStepIdx] != "undefined" && $scope.steps[nextStepIdx].enabled == false && (nextStepIdx > 0 && nextStepIdx < $scope.steps.length - 1)) {
                if (increment > 0) {
                    increment++;
                } else {
                    increment--;
                }
                nextStepIdx = currentStepIdx + increment
            }
            if ((increment > 0 && $scope.steps.length > nextStepIdx) || (increment < 0 && nextStepIdx >= 0) || increment == 0) {
                return $scope.steps[nextStepIdx];
            } else {
                return null;
            }
        }
        $scope.getCurrentIdx = function () {
            var idx = -1;
            $scope.steps.forEach(function (step, loop) {
                if ($state.current.name == step.route) {
                    idx = loop;
                }
                loop++;
            });
            return idx;
        }

        $scope.$on("$stateChangeStart", function (event, toState, toParams, fromState, fromParams) {
            var scope = event.currentScope;
            scope.fromState = fromState;
            //event.preventDefault();
            console.log(scope.formData);
        });
        $scope.validateTransition = function (fromStep, toStep) {
            if (toStep != null) {
                $scope.showNavigation = true;
                if (fromStep.state == ".profile") {
                    if (typeof $scope.formData.validated != undefined && $scope.formData.validated == true) {
                        $scope.formData.form = 'profile'
                        $scope.getOrgData();
                        return true;
                    } else {
                        $scope.findExistingPerson(fromStep, toStep);
                        $scope.currentStepIdx = $scope.getCurrentIdx();
                        return false;
                    }
                } else if (toStep.state == ".additions") {
                    $scope.validateSelectablePriceItemsOnEnter();
                    return true;
                } else if (fromStep.state == ".family" && toStep.state != ".profile") {
                    if (toStep.state == ".membership") {
                        if ($scope.formData.defaultMembership != null) {
                            $scope.setDefaultMembership($scope.formData.defaultMembership);
                        }
                        else {
                            $scope.resetMembershipValidationMessages();
                        }
                    }
                    if (typeof $scope.formData.memberConcent != "undefined" && $scope.formData.memberConcent) {
                        if ($scope.organization.signupOurTermsUrl != null && $scope.organization.signupOurTermsUrl.length > 0 && !$scope.formData.ourTerms) {
                            ModalConfirmService.confirm("Bekreft betingelser", $scope.organizationName + " krever at du bekrefter deres betingelser", "OK");
                            return false;
                        }

                        // Set group for all members in roles array if $scope.signupGroupID is set
                        $scope.toggleGroupID($scope.formData);
                        var allValidAgeAndCity = true;
                        if ($scope.validateSelectedMemberAgeAndCityRequirement($scope.formData) == false) {
                            allValidAgeAndCity = false;
                        }
                        $scope.formData.children.forEach(function (person) {
                            if ($scope.validateSelectedMemberAgeAndCityRequirement(person) == false) {
                                allValidAgeAndCity = false;
                            }
                            $scope.toggleGroupID(person);
                        });
                        $scope.formData.parents.forEach(function (person) {
                            if ($scope.validateSelectedMemberAgeAndCityRequirement(person) == false) {
                                allValidAgeAndCity = false;
                            }
                            $scope.toggleGroupID(person);
                        });
                        $scope.formData.otherFam.forEach(function (person) {
                            if ($scope.validateSelectedMemberAgeAndCityRequirement(person) == false) {
                                allValidAgeAndCity = false;
                            }
                            $scope.toggleGroupID(person);
                        });
                        if (!allValidAgeAndCity) {
                            return false;
                        }

                        if ($scope.organization.signupRequireParentsUnderAge != null && $scope.organization.signupRequireParentsUnderAge > $scope.formData.age && $scope.formData.parents.length == 0 && $scope.formData.children.length == 0) {
                            ModalConfirmService.confirm("Mangler foresatte", $scope.organizationName + " krever at du registrerer foresatte til medlemmer under " + $scope.organization.signupRequireParentsUnderAge + " år", "OK");
                            return false;
                        }
                        var memberCount = $scope.getMemberCount();
                        if (memberCount > 0) {
                            if ($scope.requireSuborgSelection && $scope.memberIsNotInSubOrg()) {
                                ModalConfirmService.confirm("Ingen gruppemedlemskap", "Du må velge en eller flere undergrupper for hvert medlem som skal meldes inn i " + $scope.organizationName, "OK");
                                return false;
                            } else {
                                if ($scope.organization.enableRankOnRoles && memberCount > 1) {
                                    ModalConfirmService.confirm("For mange haket av", "Du kan bare hake av for en person som skal bli medlem i " + $scope.organizationName + ". Fjern haken fra de som ikke skal bli medlem. Disse blir allikevel stående som familie og kan telle med i tildeling av hytter.", "OK");
                                    return false;
                                }
                                else if (toStep.state == ".group") {
                                    return true;
                                } else {
                                    $scope.newRelation = {};
                                    return true;
                                }
                            }
                        } else {
                            ModalConfirmService.confirm("Ingen meldt inn", "Du må velge minst en person før du går videre", "OK");
                            return false;
                        }
                    } else {
                        ModalConfirmService.confirm("Bekreft samtykke", "Du må samtykke i at " + $scope.organizationName + " kan behandle valgte personers personopplysninger", "OK");
                        return false;
                    }
                } else if (fromStep.state == ".family" && toStep.state != ".profile") {
                } else if (toStep.state != ".org") {
                    $scope.validateOrganizationTree();
                    return true;
                } else {
                    return true;
                }
            } else {
                return true;
            }
        }
        $scope.validateSelectedMemberAgeAndCityRequirement = function (person) {
            if (person.isMember) {
                var dob = new Date(person.birthDate);
                var diff_ms = Date.now() - dob.getTime();
                var age_dt = new Date(diff_ms);
                person.age = Math.abs(age_dt.getUTCFullYear() - 1970);

                if ($scope.organization.signupMinAgeForMember != null && person.age < $scope.organization.signupMinAgeForMember) {
                    ModalConfirmService.confirm(person.firstName + " er for ung", $scope.organizationName + " krever at medlem som meldes inn er eldre enn " + $scope.organization.signupMinAgeForMember + " år", "OK");
                    return false;
                }
                if ($scope.organization.signupMaxAgeForMember != null && person.age > $scope.organization.signupMaxAgeForMember) {
                    ModalConfirmService.confirm(person.firstName + " er for gammel", $scope.organizationName + " krever at medlem som meldes inn er yngre enn " + $scope.organization.signupMaxAgeForMember + " år", "OK");
                    return false;
                }

                if ($scope.organization.signupRequireCityMatches != null && $scope.organization.signupRequireCityMatches != '') {
                    var validCities = $scope.organization.signupRequireCityMatches.split(",").map(function (item) {
                        return item.toLowerCase().trim();
                    });
                    if (person.city == null) {
                        person.city = '';
                    }
                    if (!validCities.includes(person.city.toLowerCase())) {
                        ModalConfirmService.confirm(person.firstName + " har ugyldig poststed", $scope.organizationName + " krever at nye medlemmer er registrert med poststed " + $scope.organization.signupRequireCityMatches, "OK");
                        return false;
                    }
                }
            } else {
                return true;
            }
        }
        $scope.toggleGroupID = function (person) {   
            if ($scope.signupToGroupID != null) {
                if (typeof person.memberRoles == "undefined" || person.memberRoles == null) {
                    person.memberRoles = [];
                }
                var groupInRolesIdx = person.memberRoles.indexOf($scope.signupToGroupID);
                if (person.isMember) {
                    if (groupInRolesIdx == -1) {
                        person.memberRoles.push($scope.signupToGroupID);
                    }
                } else {
                    if (groupInRolesIdx > -1) {
                        person.memberRoles.splice(groupInRolesIdx, 1);
                    }
                }
            }
            $scope.toggleSteps();
        }
        $scope.validateSelectablePriceItemsOnEnter = function () {
            if (!$scope.formData.selectablePriceItems) $scope.formData.selectablePriceItems = [];

            $scope.selectablePriceItems.forEach(function (pi) {

                if ($scope.formData.isMember) {
                    if (!$scope.priceExistsInList($scope.formData.selectablePriceItems, pi)) {
                        var mpi = angular.copy(pi);
                        mpi.selected = false;
                        $scope.formData.selectablePriceItems.push(mpi);
                    }
                }
                $scope.formData.children.forEach(function (child) {
                    if (!child.selectablePriceItems) child.selectablePriceItems = [];

                    if (child.isMember) {
                        if (!$scope.priceExistsInList(child.selectablePriceItems, pi)) {
                            var cpi = angular.copy(pi);
                            cpi.selected = false;
                            child.selectablePriceItems.push(cpi);
                        }
                    }

                });
                $scope.formData.parents.forEach(function (parent) {
                    if (!parent.selectablePriceItems) parent.selectablePriceItems = [];

                    if (parent.isMember) {
                        if (!$scope.priceExistsInList(parent.selectablePriceItems, pi)) {
                            var ppi = angular.copy(pi);
                            ppi.selected = false;
                            parent.selectablePriceItems.push(ppi);
                        }

                    }
                });
                $scope.formData.otherFam.forEach(function (other) {
                    if (!other.selectablePriceItems) other.selectablePriceItems = [];

                    if (other.isMember) {
                        if (!$scope.priceExistsInList(other.selectablePriceItems, pi)) {
                            var opi = angular.copy(pi);
                            opi.selected = false;
                            other.selectablePriceItems.push(opi);
                        }
                    }
                });
            });
            $scope.additionsChanged();
        }

        $scope.additionsChanged = function () {
            $scope.orderTotal = 0;
            if ($scope.formData.isMember) {
                $scope.orderTotal += ($scope.formData.membership != null && $scope.formData.membership.currentPrice != null) ? parseInt($scope.formData.membership.currentPrice) : 0;
            }
            if ($scope.formData.selectablePriceItems.length > 0) {
                $scope.formData.selectablePriceItems.forEach(function (pi) {
                    if (pi.selected) { $scope.orderTotal += parseInt(pi.currentPrice); }
                });

                $scope.formData.children.forEach(function (child) {
                    if (child.isMember) {
                        $scope.orderTotal += (child.membership != null && child.membership.currentPrice != null) ? parseInt(child.membership.currentPrice) : 0;
                        child.selectablePriceItems.forEach(function (pi) {
                            if (pi.selected) { $scope.orderTotal += parseInt(pi.currentPrice); }
                        });
                    }
                });

                $scope.formData.parents.forEach(function (parent) {
                    if (parent.isMember) {
                        $scope.orderTotal += (parent.membership != null && parent.membership.currentPrice != null) ? parseInt(parent.membership.currentPrice) : 0;
                        parent.selectablePriceItems.forEach(function (pi) {
                            if (pi.selected) { $scope.orderTotal += parseInt(pi.currentPrice); }
                        });
                    }
                });

                $scope.formData.otherFam.forEach(function (other) {
                    if (other.isMember) {
                        $scope.orderTotal += (other.membership != null && other.membership.currentPrice != null) ? parseInt(other.membership.currentPrice) : 0;
                        other.selectablePriceItems.forEach(function (pi) {
                            if (pi.selected) { $scope.orderTotal += parseInt(pi.currentPrice); }
                        });
                    }
                });
            }
        }

        $scope.priceExistsInList = function (list, item) {
            var itemExists = false;
            list.forEach(function (i) {
                if (i.priceItemID == item.priceItemID) { itemExists = true; }
            });

            return itemExists;
        }
        $scope.convertToSaveableBirthDate = function (currentDate, ddlObj) {
            if (ddlObj != null) {
                var response = new Date(Date.UTC(ddlObj.year, ddlObj.month, ddlObj.day));
                return response;
            } else if (currentDate != null) {
                var date = currentDate.getDate();
                var month = currentDate.getMonth(); //Be careful! January is 0 not 1
                var year = currentDate.getFullYear();

                var response = new Date(Date.UTC(year, month, date));

                return response;
            } else {
                return null;
            }
        }
        $scope.getMemberCount = function () {
            var memberCount = 0;
            if ($scope.formData.isMember) {
                memberCount++;
            }
            $scope.formData.children.forEach(function (child) {
                if (child.isMember) {
                    memberCount++;
                }
            });
            $scope.formData.parents.forEach(function (parent) {
                if (parent.isMember) {
                    memberCount++;
                }
            });
            $scope.formData.otherFam.forEach(function (other) {
                if (other.isMember) {
                    memberCount++;
                }
            });

            return memberCount;
        }

        $scope.memberIsNotInSubOrg = function () {
            var isNotMemberInSubOrg = false;
            if ($scope.formData.isMember) {
                isNotMemberInSubOrg = !(typeof $scope.formData.memberOf != "undefined" && $scope.formData.memberOf.length > 0);
            } else {
                $scope.formData.children.forEach(function (child) {
                    if (child.isMember) {
                        isNotMemberInSubOrg = isNotMemberInSubOrg || !(typeof child.memberOf != "undefined" && child.memberOf.length > 0)
                    }
                });
                $scope.formData.parents.forEach(function (parent) {
                    if (parent.isMember) {
                        isNotMemberInSubOrg = isNotMemberInSubOrg || !(typeof parent.memberOf != "undefined" && parent.memberOf.length > 0);
                    }
                });
                $scope.formData.otherFam.forEach(function (other) {
                    if (other.isMember) {
                        isNotMemberInSubOrg = isNotMemberInSubOrg || !(typeof other.memberOf != "undefined" && other.memberOf.length > 0);
                    }
                });
            }
            return isNotMemberInSubOrg;
        }

        $scope.isValidDate = function (input) {
            return input instanceof Date && !isNaN(input);
        }

        $scope.findExistingPerson = function (fromStep, toStep) {
            if (typeof $scope.formData.website == "undefined" || $scope.formData.website == "") {
                $scope.hasSearched = true;
                $scope.existingPersons = [];
                var orgID = ServerValues.organizationID || 0;

                $scope.formData.birthDate = $scope.convertToSaveableBirthDate(null, $scope.birthDate);

                if (typeof $scope.formData.concent != "undefined" && $scope.formData.concent) {
                    var genderOK = !$scope.organization.signupRequireBirthDateGender || typeof $scope.formData.gender != 'undefined' || typeof $scope.formData.preferredGender != 'undefined';
                    var bdateOK = !$scope.organization.signupRequireBirthDateGender || $scope.isValidDate($scope.formData.birthDate);
                    var addressOK = !$scope.organization.signupShowAddress || !$scope.organization.signupRequireAddress || ($scope.formData.address && $scope.formData.zipCode && $scope.formData.city);
                    var socialnumberOK = !$scope.organization.signupRequireSocialSecurityNumber || $scope.isValidSocialnumber;

                    if (
                        genderOK && bdateOK && addressOK && socialnumberOK &&
                        typeof $scope.formData.firstName != "undefined" && $scope.formData.firstName != "" &&
                        typeof $scope.formData.lastName != "undefined" && $scope.formData.lastName != "" &&
                        typeof $scope.formData.email != "undefined" && $scope.formData.email != "" &&
                        typeof $scope.formData.mobile != "undefined" && $scope.formData.mobile != ""
                    ) {
                        $scope.saving = true;
                        $scope.formData.type = "person";
                        $scope.showNavigation = true;



                        return CallRestApi(function () { return $http.post("/rest/persons/personSignup?organizationID=" + $scope.organizationID, $scope.formData); })
                            .then(function (data) {

                                $scope.formData = data;
                                if ($scope.formData.mobile == "") { $scope.formData.mobile = null; }
                                if ($scope.formData.email == "") { $scope.formData.email = null; }
                                $scope.formData.concent = true;
                                $scope.formData.ourTerms = false;

                                var dob = new Date($scope.formData.birthDate);
                                var diff_ms = Date.now() - dob.getTime();
                                var age_dt = new Date(diff_ms);
                                $scope.formData.age = Math.abs(age_dt.getUTCFullYear() - 1970);

                                $scope.vaidateFormData();

                                if ($scope.formData.validated == false) {
                                    $scope.formData.form = 'validate';
                                    $scope.showNavigation = false;
                                }
                                if ($scope.formData.validated && !$scope.formData.hasLogin) {
                                    if (typeof $scope.formData.email != "undefined" && $scope.formData.email != null && $scope.formData.email != "") {
                                        $scope.formData.username = $scope.formData.email;
                                        $scope.validateUsername();
                                    }
                                    $scope.formData.form = 'username';
                                    $scope.showNavigation = false;
                                }

                                $scope.saving = false;
                                if ($scope.formData.validated && $scope.formData.hasLogin) {
                                    $scope.formData.form = 'profile';
                                    $scope.showNavigation = false;
                                    $scope.next();
                                }
                            }, function (error) {
                                ModalConfirmService.confirm("Feil ved lagring", "Det skjedde en feil ved opprettelse av personen:<br/>" + error, "OK");
                                $scope.saving = false;

                            });
                    } else {
                        if ($scope.organization.signupRequireBirthDateGender || ($scope.organization.signupShowAddress && $scope.organization.signupRequireAddress)) {
                            var requireString = "";
                            if ($scope.organization.signupRequireBirthDateGender) requireString = "fødselsdato / kjønn";
                            if ($scope.organization.signupRequireAddress) {
                                if (requireString.length > 0) requireString += " og ";
                                requireString += "adressefelter"
                            }
                            if ($scope.organization.signupRequireSocialSecurityNumber) {
                                if (requireString.length > 0) requireString += " og ";
                                requireString += "gyldig fødselsnummer"
                            }
                            ModalConfirmService.confirm("Manglede utfylling", "Du må fylle ut fornavn, etternavn, epost og/eller mobil samt " + requireString, "OK");
                        } else {
                            ModalConfirmService.confirm("Manglede utfylling", "Du må fylle ut minimum fornavn, etternavn samt epost og/eller mobil<br/>I tillegg anbefaler vi at du registrerer fødselsdato og kjønn", "OK");
                        }
                        return false;
                    }
                } else {
                    ModalConfirmService.confirm("Bekreft samtykke", "Du må samtykke at personopplysninger lagres i Rubic", "OK");
                    return false;
                }
            } else {
                ModalConfirmService.confirm("Robot detektert", "Vi mistenker at du er en robot og registreringen vil derfor ikke fungere", "OK");
            }
        };
        $scope.validateCode = function () {
            return CallRestApi(function () { return $http.get("/rest/persons/" + $scope.formData.id + "/validatecode/" + $scope.formData.personValCode.toString().padStart(6, '0') + "/true"); })
                .then(function (data) {

                    $scope.formData.validated = data;

                    if ($scope.formData.validated) {
                        if ($scope.formData.hasLogin) {
                            $scope.next();
                        } else {
                            if (typeof $scope.formData.email != "undefined" && $scope.formData.email != null && $scope.formData.email != "") {
                                $scope.formData.username = $scope.formData.email;
                                $scope.validateUsername();
                            } else if (typeof $scope.formData.mobile != "undefined" && $scope.formData.mobile != null && $scope.formData.mobile != "") {
                                $scope.formData.username = $scope.formData.mobile;
                                $scope.validateUsername();
                            }
                            $scope.formData.form = 'username';
                            $scope.showNavigation = false;
                        }
                    } else {
                        ModalConfirmService.confirm("Feil under validering", "Koden du skrev inn er feil. Prøv igjen eller kontakt Rubic Support", "OK");

                    }

                },
                    function (error) {
                        ModalConfirmService.confirm("Feil under validering", "Koden du skrev inn er feil. Prøv igjen eller kontakt Rubic Support", "OK");
                    });
        }
        $scope.createUsername = function () {

            var formValid = false;
            if (typeof $scope.formData.username == "undefined" || $scope.formData.username == null || $scope.formData.username == "") {
                ModalConfirmService.confirm("Feil under validering", "Du må skrive inn et brukernavn", "OK");
            } else if (typeof $scope.formData.password == "undefined" || $scope.formData.password == null || $scope.formData.password == "") {
                ModalConfirmService.confirm("Feil under validering", "Du må skrive inn et passord", "OK");
            } else if ($scope.formData.password.length < 8) {
                ModalConfirmService.confirm("Feil under validering", "Passordet må være minst 8 tegn langt og bør inneholde både bokstaver, tall og spesialtegn", "OK");
            } else if (typeof $scope.formData.confirmPassword == "undefined" || $scope.formData.confirmPassword == null || $scope.formData.confirmPassword == "") {
                ModalConfirmService.confirm("Feil under validering", "Du må bekrefte passordet", "OK");
            } else if ($scope.formData.password != $scope.formData.confirmPassword) {
                ModalConfirmService.confirm("Feil under validering", "Passordene er ikke like", "OK");
            } else if ($scope.formData.usernameExists) {
                ModalConfirmService.confirm("Feil under validering", "Brukernavnet du har oppgitt er brukt hos en annen profil. Velg et annet brukernavn", "OK");
            } else {
                return CallRestApi(function () { return $http.post("/rest/persons/" + $scope.formData.id + "/createMyLogin/", $scope.formData); })
                    .then(function (data) {

                        $scope.formData = data;
                        $scope.formData.validated = true;
                        $scope.vaidateFormData();
                        $scope.next();


                    }, function (error) {
                        ModalConfirmService.confirm("Feil under validering", error, "OK");
                    });
            }
        }
        $scope.validateUsername = function () {

            return CallRestApi(function () { return $http.post("/rest/persons/" + $scope.formData.id + "/myLoginExists", { "username": $scope.formData.username }); })
                .then(function (data) {

                    $scope.formData.usernameExists = data;

                });
        }
        $scope.resetForm = function () {
            $scope.formData = { form: 'profile', countryCode: '47' };
        }

        $scope.selectRootOrg = function (person) {
            person.memberOf = [];
            person.isMember = !person.isMember;
            $scope.toggleSteps();
        }

        $scope.activeSteps = function () {
            var activeSteps = $scope.steps.filter(s => s.enabled).length;
            console.log("active steps", activeSteps);
            console.log("steps", $scope.currentStepIdx);
            return activeSteps;
        }

        $scope.toggleSteps = function () {
            var anySelectedPersonsNotMember = false;
            if ($scope.formData.isMember && !$scope.formData.isAlreadyMember) { anySelectedPersonsNotMember = true; }
            if ($scope.formData.children.filter(c => c.isMember && !c.isAlreadyMember).length > 0) { anySelectedPersonsNotMember = true; }
            if ($scope.formData.parents.filter(c => c.isMember && !c.isAlreadyMember).length > 0) { anySelectedPersonsNotMember = true; }
            if ($scope.formData.otherFam.filter(c => c.isMember && !c.isAlreadyMember).length > 0) { anySelectedPersonsNotMember = true; }

            if ($scope.signupToGroupID > 0) {
                if (anySelectedPersonsNotMember) {
                    console.log("Show all steps");
                    $scope.steps.forEach(function (step) { step.enabled = true; });
                } else {
                    console.log("Hide member-steps");
                    $scope.steps.forEach(function (step,idx) { step.enabled = idx < 2 || step.state == ".group"; });
                }
            }
        }

        $scope.selectSubOrg = function (person, subOrgID) {
            if (person.memberOf) {
                var index = person.memberOf.indexOf(subOrgID);
                if (index >= 0) {
                    person.memberOf.splice(index);
                }
                else {
                    person.memberOf.push(subOrgID);
                }
            }
            if (!person.isMember) {
                person.isMember = true;
            }
        }

        $scope.signOffMember = function (person, orgID) {
            person.isMember = !person.isMember;
            var rootOrgID = parseInt($scope.organizationID);
            var changedOrgID = parseInt(orgID);
            var removedMain = !person.isMember && changedOrgID == rootOrgID;
            if (!person.isMember && changedOrgID != rootOrgID) {
                person.isMember = true;
            } else if (removedMain) {
                person.memberOf = [];
            }
        }

        $scope.vaidateFormData = function () {
            if (typeof $scope.formData.birthDate == "string") {
                $scope.formData.birthDate = new Date($scope.formData.birthDate);
            }
            if ($scope.formData.birthDate != null) {
                $scope.birthDate = { day: 0, month: 0, year: 0 };
                $scope.birthDate.day = $scope.formData.birthDate.getDate();
                $scope.birthDate.month = $scope.formData.birthDate.getMonth();
                $scope.birthDate.year = $scope.formData.birthDate.getFullYear();
                console.log($scope.birthDate);
            }
        }
        $scope.addRelation = function (type) {
            $scope.newRelation = {
                type: type,
                showForm: true,
                form: 'showForm'
            };

            if ($scope.newRelation.type == "other") {
                $scope.newRelation.address = $scope.formData.address;
                $scope.newRelation.zipCode = $scope.formData.zipCode;
                $scope.newRelation.city = $scope.formData.city;
            } else {
                $scope.newRelation.email = $scope.formData.email;
                $scope.newRelation.mobile = $scope.formData.mobile;
                $scope.newRelation.address = $scope.formData.address;
                $scope.newRelation.zipCode = $scope.formData.zipCode;
                $scope.newRelation.city = $scope.formData.city;
            }
            $scope.familiyScreen.form = 'showForm';
            $scope.isValidSocialnumber = false;
            $scope.showNavigation = false;
        }


        $scope.addRelatedPerson = function () {
            if (typeof $scope.newRelation.concent != "undefined" && $scope.newRelation.concent) {
                $scope.newRelation.birthDate = $scope.convertToSaveableBirthDate(null, $scope.relBirthDate);

                var genderOK = !$scope.organization.signupRequireBirthDateGender || typeof $scope.newRelation.gender != 'undefined' || typeof $scope.newRelation.preferredGender != 'undefined';
                var bdateOK = !$scope.organization.signupRequireBirthDateGender || $scope.isValidDate($scope.newRelation.birthDate);
                var addressOK = !$scope.organization.signupShowAddress || !$scope.organization.signupRequireAddress || ($scope.newRelation.address && $scope.newRelation.zipCode && $scope.newRelation.city);
                var socialnumberOK = !$scope.organization.signupRequireSocialSecurityNumber || $scope.isValidSocialnumber;

                if (
                    genderOK && bdateOK && addressOK && socialnumberOK &&
                    typeof $scope.newRelation.firstName != "undefined" && $scope.newRelation.firstName != "" &&
                    typeof $scope.newRelation.lastName != "undefined" && $scope.newRelation.lastName != "" &&
                    (
                        (typeof $scope.newRelation.email != "undefined" && $scope.newRelation.email != "") ||
                        (typeof $scope.newRelation.mobile != "undefined" && $scope.newRelation.mobile != "")
                    )
                ) {
                    $scope.saving = true;

                    return CallRestApi(function () { return $http.post("/rest/persons/personSignup", $scope.newRelation); })
                        .then(function (data) {
                            //storing these properties so they can be added to serverresponse
                            var relType = $scope.newRelation.type;
                            var isMember = $scope.newRelation.isMember;
                            var memberOf = $scope.newRelation.memberOf;
                            $scope.newRelation = data;
                            if ($scope.newRelation.mobile == "") { $scope.newRelation.mobile = null; }
                            if ($scope.newRelation.email == "") { $scope.newRelation.email = null; }
                            $scope.newRelation.birthDate = new Date($scope.newRelation.birthDate);

                            //adding to serverResponse
                            $scope.newRelation.type = relType;
                            $scope.newRelation.isMember = isMember;
                            $scope.newRelation.memberOf = memberOf;
                            $scope.newRelation.concent = true;
                            
                            $scope.saving = false;
                            if ($scope.newRelation.validated) {
                                $scope.createRelation();
                                $scope.familiyScreen.form = 'selectPersons';
                                $scope.showNavigation = true;
                            } else {
                                $scope.newRelation.showForm = false;
                                $scope.familiyScreen.form = 'validate';
                                $scope.showNavigation = false;
                            }
                        }, function (error) {
                            ModalConfirmService.confirm("Feil ved lagring", "Det skjedde en feil ved opprettelse av personen:<br/>" + error, "OK");
                            $scope.saving = false;

                        });
                } else {
                    if ($scope.organization.signupRequireBirthDateGender || $scope.organization.signupRequireAddress) {
                        var requireString = "";
                        if ($scope.organization.signupRequireBirthDateGender) requireString = "fødselsdato / kjønn";
                        if ($scope.organization.signupRequireAddress) {
                            if ($scope.organization.signupRequireBirthDateGender) requireString += " og ";
                            requireString += "adressefelter"
                        }
                        ModalConfirmService.confirm("Manglede utfylling", "Du må fylle ut fornavn, etternavn, epost og/eller mobil samt " + requireString, "OK");
                    } else {
                        ModalConfirmService.confirm("Manglede utfylling", "Du må fylle ut minimum fornavn, etternavn samt epost og/eller mobil<br/>I tillegg anbefaler vi at du registrerer fødselsdato og kjønn", "OK");
                    }
                    return false;
                }
            } else {
                ModalConfirmService.confirm("Bekreft samtykke", "Du må samtykke at personopplysninger lagres i Rubic", "OK");
                return false;
            }





        }
        $scope.cancelRelatedPerson = function () {
            $scope.newRelation = {};
            $scope.familiyScreen.form = 'selectPersons';
            $scope.showNavigation = true;
        }
        $scope.createRelation = function () {


            CallRestApi(function () { return $http.get("/rest/persons/" + $scope.formData.id + "/createRelation/" + $scope.newRelation.type + "/" + $scope.newRelation.id); })
                .then(function (data) {

                    if ($scope.newRelation.type == "child") {
                        $scope.formData.children.push(angular.copy($scope.newRelation));
                    } else if ($scope.newRelation.type == "other") {
                        $scope.formData.otherFam.push(angular.copy($scope.newRelation));
                    } else {
                        $scope.formData.parents.push(angular.copy($scope.newRelation));
                    }
                    $scope.newRelation = {};
                    $scope.saving = false;
                    $scope.setDefaultMemberships();
                    $scope.familiyScreen.form = 'selectPersons';
                    $scope.showNavigation = true;

                }, function (error) {
                    ModalConfirmService.confirm("Feil ved lagring", "Det skjedde en feil ved opprettelse av personen:<br/>" + error, "OK");
                    $scope.saving = false;

                });



        }

        $scope.validateRelationCode = function () {
            CallRestApi(function () { return $http.get("/rest/persons/" + $scope.newRelation.id + "/validatecode/" + $scope.newRelation.personValCode.toString().padStart(6, '0') + "/false"); })
                .then(function (data) {

                    $scope.newRelation.validated = data;

                    if ($scope.newRelation.validated) {
                        $scope.createRelation();
                    } else {
                        ModalConfirmService.confirm("Feil under validering", "Koden du skrev inn er feil. Prøv igjen eller kontakt Rubic Support", "OK");
                    }
                });
        }

        $scope.getAttributeConfig = function (attrName) {
            var attrCfg = null;
            $scope.attributes.forEach(function (a) {
                if (a.attributePropertyName == attrName) {
                    attrCfg = a;
                }
            });

            return attrCfg;
        }

        $scope.getMemberSignupItem = function (person) {
            var item = {
                personID: person.id,
                organizationID: ServerValues.organizationID,
                membershipID: person.membership ? person.membership.membershipID : null,
                membershipPayerPersonID: person.membership ? person.membership.membershipPayerPersonID : null,
                additionalPriceItems: [],
                subOrgIDs: [],
                attributes: [],
                roles: []
            };

            if (typeof person.attr != "undefined") {
                for (var key in person.attr) {
                    
                    var dateValid = false;
                    var attrCfg = $scope.getAttributeConfig(key);
                    if (attrCfg != null && attrCfg.attributeProps.controlType == "Date") {
                        var momentObj = moment(person.attr[key], 'dd.MM.yyyy');
                        dateValid = momentObj.isValid();
                    }
                    if (typeof person.attr[key] == "object" && person.attr[key].length > 0) {
                        person.attr[key] = person.attr[key].join(",");
                    }
                    else if (dateValid) {
                        var options = { day: "2-digit", month: "2-digit", year: "numeric" };
                        person.attr[key] = person.attr[key].toLocaleDateString("no-NO", options);
                    }
                    item.attributes.push({ name: key, value: person.attr[key].toString() });
                }
            }

            if (typeof person.memberRoles != "undefined" && person.memberRoles) {
                person.memberRoles.forEach(function (orgID) {
                    if (orgID != null && !isNaN(orgID)) {
                        item.roles.push({ "organizationID": orgID, "roleID": 2 });
                    }
                });
            }

            if (typeof person.memberOf != "undefined" && person.memberOf) {
                item.subOrgIDs = person.memberOf;
            }

            if (typeof person.selectablePriceItems != "undefined" && person.selectablePriceItems) {
                person.selectablePriceItems.forEach(function (pi) {
                    if (pi.selected) {
                        item.additionalPriceItems.push({ "priceItemID": pi.priceItemID, "quantity": 1 });
                    }
                });
            }

            return item;
        }

        /* START MEMBERSHIP METHODS TO BE DELETED */
        $scope.filterMemberships = function (isParentType) {
            return function (membership) {
                if (isParentType) {
                    if (!$scope.anyFamilyMemberships()) {
                        return membership.membershipTypeID != 3;
                    } else {
                        return true;
                    }
                } else {
                    if ($scope.anyFamilyMemberships()) {
                        return membership.membershipTypeID != 2;
                    } else {
                        return membership.membershipTypeID == 1;
                    }
                }
            }
        }
        $scope.setDefaultMemberships = function () {
            if (!$scope.formData.membership) {
                $scope.formData.membership = $scope.getFirstAvailableSingleMembership();
            }
            $scope.formData.parents.forEach(function (parent) {
                if (!parent.membership) {
                    parent.membership = $scope.getFirstAvailableSingleMembership();
                }
            });
            $scope.formData.children.forEach(function (child) {
                if (!child.membership) {
                    child.membership = $scope.getFirstAvailableSingleMembership();
                }
            });
            $scope.formData.otherFam.forEach(function (other) {
                if (!other.membership) {
                    other.membership = $scope.getFirstAvailableSingleMembership();
                }
            });
        }
        $scope.validateMemberships = function () {
            var meIsParent = $scope.formData.children.length > 0 || $scope.formData.otherFam.length > 0;

            if ($scope.anyFamilyMemberships()) {
                var familyMembership = $scope.getFamilyMembershipInFam();
                var familyMember = $scope.getFamilyMemberInFam();
                familyMember.membershipPayerPersonID = familyMembership.membershipPayerPersonID;


                // Make sure that the person that has set familiymembership is parent or me (with children)
                if (meIsParent) {
                    // Make sure that familymembership is set on ME
                    $scope.formData.membership = familyMembership;
                } else {
                    $scope.formData.membership = familyMember;
                }

                // Set familymember type on all other persons
                $scope.formData.children.forEach(function (child) {
                    child.membership = familyMember;
                });
                var anyParentFamMemberships = false;
                $scope.formData.parents.forEach(function (parent) {
                    if (meIsParent || parent.membership.membershipTypeID != 2 || anyParentFamMemberships) {
                        parent.membership = familyMember;
                    }
                    anyParentFamMemberships = parent.membership.membershipTypeID == 2 || anyParentFamMemberships;
                });
                if (!anyParentFamMemberships) {
                    if ($scope.formData.parents.length > 0) {
                        $scope.formData.parents[0].membership = familyMembership;
                    } else {
                        $scope.formData.membership = familyMembership;
                    }
                }
                $scope.formData.otherFam.forEach(function (other) {
                    other.membership = familyMember;
                });
            } else {
                // Make sure that all persons has single memberships
                var singleMember = $scope.getFirstAvailableSingleMembership();
                singleMember.membershipPayerPersonID = $scope.formData.id;

                if ($scope.formData.membership.membershipTypeID != 1) { $scope.formData.membership = singleMember; }
                $scope.formData.membership.membershipPayerPersonID = $scope.formData.id;

                $scope.formData.children.forEach(function (child) {
                    if (child.membership.membershipTypeID != 1) { child.membership = singleMember; }
                    child.membership.membershipPayerPersonID = $scope.formData.id;
                });
                $scope.formData.parents.forEach(function (parent) {
                    if (parent.membership.membershipTypeID != 1) { parent.membership = singleMember; }
                    parent.membership.membershipPayerPersonID = $scope.formData.id;
                });
                $scope.formData.otherFam.forEach(function (other) {
                    if (other.membership.membershipTypeID != 1) { other.membership = singleMember; }
                    other.membership.membershipPayerPersonID = $scope.formData.id;
                });
            }
        }

        $scope.getFamilyMembershipInFam = function () {
            var familyMembership = null;
            if ($scope.formData.membership.membershipTypeID == 2) {
                familyMembership = $scope.formData.membership;
                familyMembership.membershipPayerPersonID = $scope.formData.id;
            } else {
                $scope.formData.parents.forEach(function (parent) {
                    if (parent.membership.membershipTypeID == 2) {
                        familyMembership = parent.membership;
                        familyMembership.membershipPayerPersonID = parent.id;
                    }
                });
            }
            return familyMembership;
        }
        $scope.getFamilyMemberInFam = function () {
            var familyMember = null;
            $scope.memberships.forEach(function (membership) {
                if (membership.membershipTypeID == 3) {
                    familyMember = membership;
                }
            });
            return familyMember;
        }
        $scope.getFirstAvailableSingleMembership = function () {
            var singleMember = null;
            $scope.memberships.forEach(function (membership) {
                if (membership.membershipTypeID == 1) {
                    singleMember = membership;
                }
            });
            return singleMember;
        }
        $scope.anyFamilyMemberships = function () {
            var anyFamilyMemberships = $scope.formData.membership && $scope.formData.membership.membershipTypeID == 2;
            if (!anyFamilyMemberships) {
                $scope.formData.parents.forEach(function (parent) {
                    anyFamilyMemberships = anyFamilyMemberships || parent.membership.membershipTypeID == 2;
                });
            }
            if (!anyFamilyMemberships) {
                $scope.formData.children.forEach(function (child) {
                    anyFamilyMemberships = anyFamilyMemberships || child.membership.membershipTypeID == 2;
                });
            }
            if (!anyFamilyMemberships) {
                $scope.formData.otherFam.forEach(function (other) {
                    anyFamilyMemberships = anyFamilyMemberships || other.membership.membershipTypeID == 2;
                });
            }
            return anyFamilyMemberships;
        }
        /* END MEMBERSHIP METHODS TO BE DELETED */

        $scope.selectableMemberships = function () {
            return function (membership) {
                return membership.membershipTypeID != 3 && membership.roleID == 2;
            }
        }
        $scope.selectableMembershipsByType = function (typeID) {
            return function (membership) {
                return membership.membershipTypeID == typeID && membership.roleID == 2;
            }
        }

        $scope.setDefaultMembership = function (selectedMembership) {
            $scope.formData.defaultMembership = selectedMembership;
            $scope.famTotCnt = 0;
            $scope.famAdultCnt = 0;
            $scope.famChildrenCnt = 0;
            $scope.resetMembershipValidationMessages();

            if (selectedMembership.membershipTypeID == 1) {
                if ($scope.formData.isMember) {
                    $scope.formData.membership = selectedMembership;
                }
                $scope.formData.parents.forEach(function (parent) {
                    if (parent.isMember) {
                        parent.membership = selectedMembership;
                    }
                });
                $scope.formData.children.forEach(function (child) {
                    if (child.isMember) {
                        child.membership = selectedMembership;
                    }
                });
                $scope.formData.otherFam.forEach(function (other) {
                    if (other.isMember) {
                        other.membership = selectedMembership;
                    }
                });
            } else if (selectedMembership.membershipTypeID == 2) {
                var famMembershipSet = false;
                var familyMember = $scope.getFamilyMemberType();

                if ($scope.formData.isMember) {
                    familyMember.membershipPayerPersonID = $scope.formData.id;
                    $scope.formData.membership = selectedMembership;
                    famMembershipSet = true;
                    incrementFamCounters($scope.formData, selectedMembership.maxAgeChildren);
                }
                $scope.formData.parents.forEach(function (parent) {
                    if (parent.isMember) {
                        incrementFamCounters(parent, selectedMembership.maxAgeChildren);
                        if (!famMembershipSet) {
                            familyMember.membershipPayerPersonID = parent.id;
                            parent.membership = selectedMembership;
                            famMembershipSet = true;
                        }
                    }
                });
                $scope.formData.otherFam.forEach(function (other) {
                    if (other.isMember) {
                        incrementFamCounters(other, selectedMembership.maxAgeChildren);
                    }
                    if (!famMembershipSet) {
                        familyMember.membershipPayerPersonID = other.id;
                        other.membership = selectedMembership;
                        famMembershipSet = true;
                    }
                });
                $scope.formData.children.forEach(function (child) {
                    if (child.isMember) {
                        incrementFamCounters(child, selectedMembership.maxAgeChildren);
                        if (!famMembershipSet) {
                            familyMember.membershipPayerPersonID = child.id;
                            child.membership = selectedMembership;
                            famMembershipSet = true;
                        }
                    }
                });
                var selectedMembershipIsAvailable = checkMembershipValid(selectedMembership);
                if (!selectedMembershipIsAvailable) {
                    $scope.formData.defaultMembership = null;
                }

                // Set familymembers
                $scope.formData.parents.forEach(function (parent) {
                    if (parent.isMember && parent.membership != selectedMembership) {
                        parent.membership = familyMember;
                    }
                });
                $scope.formData.otherFam.forEach(function (other) {
                    if (other.isMember && other.membership != selectedMembership) {
                        other.membership = familyMember;
                    }
                });
                $scope.formData.children.forEach(function (child) {
                    if (child.isMember && child.membership != selectedMembership) {
                        child.membership = familyMember;
                    }
                });
            }
        }

        var incrementFamCounters = function (person, maxAgeChildren) {
            var now = new Date();
            if (maxAgeChildren) {
                var birthDate = person.birthDate ? new Date(person.birthDate) : new Date(1900, 01);
                var age = now.getFullYear() - birthDate.getFullYear();
                if (isChild(age, maxAgeChildren)) {
                    $scope.famChildrenCnt++;
                }
                else {
                    $scope.famAdultCnt++;
                }
            }
            $scope.famTotCnt++;
        }

        var isChild = function (age, maxAgeChildren) {
            if (!age) {
                return false;
            }
            else if (age <= maxAgeChildren) {
                return true;
            }
            else {
                return false;
            }
        }

        var checkMembershipValid = function (m) {
            if (m.maxAdults || m.maxChildren) {
                if (m.maxAgeChildren) {
                    if ($scope.famChildrenCnt > m.maxChildren && $scope.famAdultCnt > m.maxAdults) {
                        m.validationMessage = "Medlemskapet tillater kun " + m.maxAdults + " voksne og " + m.maxChildren + " barn (opp til " + m.maxAgeChildren + " år)";
                        return false;
                    }
                    else if (m.maxAdults && $scope.famAdultCnt > m.maxAdults) {
                        m.validationMessage = "Medlemskapet tillater kun " + m.maxAdults + " voksne (over " + m.maxAgeChildren + " år)";
                        return false;
                    }
                    else if (m.maxChildren && $scope.famChildrenCnt > m.maxChildren) {
                        m.validationMessage = "Medlemskapet tillater kun " + m.maxChildren + " barn (opp til " + m.maxAgeChildren + " år)";
                        return false;
                    }
                    else {
                        return true;
                    }
                }
                else {
                    m.maxTotal = m.maxAdults + m.maxChildren;
                    if ($scope.famTotCnt > m.maxTotal) {
                        m.validationMessage = "Medlemskapet tillater kun " + m.maxTotal + " personer.<br/>";
                        return false;
                    }
                    else {
                        return true;
                    }
                }

            }
            else {
                return true;
            }
        }

        $scope.resetMembershipValidationMessages = function () {
            $scope.memberships.forEach(function (membership) {
                membership.validationMessage = null;
            })
        }


        $scope.getFamilyMemberType = function () {
            var familyMember = null;
            $scope.memberships.forEach(function (membership) {
                if (membership.membershipTypeID == 3) {
                    familyMember = membership;
                }
            });
            return familyMember;
        }

        // function to process the form
        $scope.register = function () {
            $scope.currentState = $state.current;
            var fromStep = $scope.getStep(0);
            if ($scope.validateTransition(fromStep, "COMPLETE")) {

                $scope.formData.birthDate = $scope.convertToSaveableBirthDate($scope.formData.birthDate, null);

                var memberSignup = [];
                if ($scope.formData.isMember) {
                    if ($scope.formData.membership && $scope.formData.membership.membershipTypeID == 1) { $scope.formData.membership.membershipPayerPersonID = $scope.formData.id; }
                    memberSignup.push($scope.getMemberSignupItem($scope.formData));
                }
                $scope.formData.parents.forEach(function (parent) {
                    if (typeof parent.isMember != "undefined" && parent.isMember) {
                        if (parent.membership && parent.membership.membershipTypeID == 1) { parent.membership.membershipPayerPersonID = $scope.formData.id; }
                        memberSignup.push($scope.getMemberSignupItem(parent));
                    }
                });
                $scope.formData.children.forEach(function (child) {
                    if (typeof child.isMember != "undefined" && child.isMember) {
                        if (child.membership && child.membership.membershipTypeID == 1) { child.membership.membershipPayerPersonID = $scope.formData.id; }
                        memberSignup.push($scope.getMemberSignupItem(child));
                    }
                });
                $scope.formData.otherFam.forEach(function (other) {
                    if (typeof other.isMember != "undefined" && other.isMember) {
                        if (other.membership && other.membership.membershipTypeID == 1) { other.membership.membershipPayerPersonID = $scope.formData.id; }
                        memberSignup.push($scope.getMemberSignupItem(other));
                    }
                });

                $scope.saving = true;
                return CallRestApi(function () { return $http.post("/rest/persons/memberSignup/" + ServerValues.organizationID + "/" + $scope.formData.id, memberSignup); })
                    .then(function (data) {
                        var dialogFeedback = data.feedback.replace(/(?:\r\n|\r|\n)/g, "<br/>");

                        if ($scope.redirectUrl == null || $scope.redirectUrl == "") {                            
                            $scope.redirectUrl = "/";
                            if (data.invoices != null && data.invoices.length > 0) {                               
                                if (data.redirectUrl.indexOf("?") > -1) {
                                    $scope.redirectUrl = data.redirectUrl + "&callbackUrl=/";
                                } else {
                                    $scope.redirectUrl = data.redirectUrl + "?callbackUrl=/";
                                }
                            }
                        } else {
                            if (data.invoices != null && data.invoices.length > 0) {
                                if ($scope.redirectUrl.indexOf("/Event") > -1) { dialogFeedback += "<br/>Etter betaling vil du komme tilbake påmeldingsarrangementet<br/>"; }

                                if (data.redirectUrl.indexOf("?") > -1) {
                                    $scope.redirectUrl = data.redirectUrl + "&callbackUrl=" + $scope.redirectUrl;
                                } else {
                                    $scope.redirectUrl = data.redirectUrl + "?callbackUrl=" + $scope.redirectUrl;
                                }
                                
                            }
                        }


                        ModalConfirmService.confirm("Velkommen", dialogFeedback, "OK", undefined, "static")
                            .then(function () {
                                window.location.href = $scope.redirectUrl;
                            });

                        $scope.saving = false;
                    }, function (error) {
                        ModalConfirmService.confirm("Feil ved registrering", "Det skjedde en feil ved opprettelse av medlemmet:<br/>" + error, "OK");
                        $scope.saving = false;
                    });


            }
        };

        $scope.getMemberships = function () {
            CallApi(function () { return $http.get('/api/OrganizationsApi/GetMemberships/' + ServerValues.organizationID) })
                .then(function (memberships) {

                    $scope.memberships = [];
                    memberships.forEach(function (membership) {
                        if (membership.roleID == 2) {
                            if (membership.currentPrice != null) {
                                membership.caption = membership.membershipName + " - " + membership.currentPrice + " kr";
                            } else {
                                membership.caption = membership.membershipName;
                            }
                            $scope.memberships.push(membership);
                        }
                    });
                    $scope.setDefaultMemberships();
                    console.log($scope.memberships);
                }, function (error) {
                    $scope.errorGettingMemberships = true;
                });
        };


        $scope.getPersonOrg = function () {
            $http.get('/api/Members/GetPersonOrg/' + $scope.formData.id + '/' + ServerValues.organizationID)
                .success(function (data, status, headers, config) {
                    $scope.personOrg = data.data[0];
                })
                .error(function (data, status, headers, config) {
                    $scope.userAllowed = false;
                }
                );
        };
        $scope.getMembershipPayers = function () {
            $http.get('/api/Members/GetMembershipPayers/' + $scope.formData.id + '/' + ServerValues.organizationID)
                .success(function (data, status, headers, config) {
                    $scope.membershipPayers = data.data[0];
                })
                .error(function (data, status, headers, config) {
                    $scope.userAllowed = false;
                }
                );
        };
        $scope.getAttributes = function () {
            $http.get('/api/OrganizationsApi/GetAttributes/' + ServerValues.organizationID)
                .success(function (data, status, headers, config) {
                    $scope.attributes = data.data[0];
                }).error(function (data, status, headers, config) {
                    $scope.userAllowed = false;
                })
        }

        $scope.getAttrSuggestions = function (searchExpression, attr) {
            if (attr.allowSuggestions) {
                return $http.get('/api/OrganizationsApi/GetCustomAttributeSuggestions/' + ServerValues.organizationID + '/' + attr.attributeProperty + '/' + searchExpression)
                    .then(function (response) {
                        return response.data.data;
                    });
            }
            return [];
        }

        $scope.getDistrictSuggestions = function (searchExpression) {
            return $http.get('/api/OrganizationsApi/GetDistrictSuggestions/' + ServerValues.organizationID + '/' + searchExpression)
                .then(function (response) {
                    return response.data.data;
                });
        }
        $scope.getGroups = function () {
            return CallApi(function () { return $http.get("/api/OrganizationsApi/GetOrganizationTree/" + $scope.organizationID); })
                .then(function (orgs) {
                    $scope.organizationTree = orgs;

                    $scope.validateOrganizationTree();

                })
                .then(function (trainingFeeAvailable) {
                    $scope.showTrainingFeeButton = trainingFeeAvailable;
                });
        };
        $scope.getSubOrganizations = function () {
            CallApi(function () { return $http.get("/api/OrganizationsApi/GetSubOrganizations/" + $scope.organizationID); })
                .then(function (orgs) {
                    $scope.subOrganizations = orgs;

                });
        };
        $scope.getSelectablePriceItems = function () {
            CallApi(function () { return $http.get("/api/SalesApi/GetPriceItems/onlySelectable?organizationID=" + $scope.organizationID); })
                .then(function (priceItems) {
                    $scope.selectablePriceItems = priceItems;
                });
        };

        $scope.getOrgData = function () {
            if (ServerValues.organizationID) {
                //$scope.getPersonOrg();
                $scope.getAttributes();
                $scope.getMemberships();
                //$scope.getMembershipPayers();
                $scope.getGroups();
                $scope.getSubOrganizations();
                $scope.getSelectablePriceItems();

                if (($scope.formData.children == null || $scope.formData.children.length == 0) && $scope.formData.mode == "child" ) {
                    $scope.addRelation('child');
                }
            }
        }

        // On page reload, always load first step
        $scope.currentStepIdx = 0;
        if ($state.current != null && $state.current.name != "form.profile") {
            //window.location.href = "#" + $scope.steps[0].route;
            $state.go("form.profile");
        }



        $scope.searchExpression = '';
        $scope.organizations = [];
        $scope.getOrganizations = function () {
            val = $scope.searchExpression || '';

            if (val.length > 0) {
                var url = '/api/OrganizationsApi/searchOrgName/' + val;
                $scope.searching = true;
                return CallApi(function () { return $http.get(url) })
                    .then(function (data) {
                        $scope.organizations = data;
                        $scope.searching = false;
                        return [];
                    }, function (error) {
                        ModalConfirmService.confirm("Error", error.toString(), "OK");
                        $scope.organizations = [];
                        $scope.searching = false;
                        return ['Ingen treff'];
                    }
                    );
            } else {
                $scope.searching = false;
                $scope.organizations = [];
            }

        };
        $scope.validateOrganizationTree = function () {

            var numMembers = $scope.formData.isMember ? 1 : 0;
            var numParents = $scope.formData.parents != null ? $scope.formData.parents.filter(p => p.isMember).length : 0;
            var numChildren = $scope.formData.children != null ?$scope.formData.children.filter(c => c.isMember).length : 0;
            var numOther = $scope.formData.otherFam != null ? $scope.formData.otherFam.filter(o => o.isMember).length : 0;
            var numTotal = numMembers + numParents + numChildren + numOther;

            $scope.columns = numTotal == 1 ? 12 : numTotal == 2 ? 6 : 4;
            var maxChars = numTotal == 1 ? 150 : numTotal == 2 ? 50 : 30;
            
            $scope.organizationTree.forEach(function (org) {
                org.prefix = "";
                org.path = $scope.setOrganizationPath(org);
                org.visible = false;
                org.enabled = false;
                var i = 2;
                while (i < org.organizationTypeID) {
                    org.prefix += "-";
                    i++;
                }
                if (numTotal < 3) {
                    org.displayName = org.organizationName.length > (maxChars - org.organizationTypeID) ? org.organizationName.substring(0, (maxChars - org.organizationTypeID)) + "..." : org.organizationName;
                } else {
                    org.displayName = org.organizationShortName.length > (maxChars - org.organizationTypeID) ? org.organizationShortName.substring(0, (maxChars - org.organizationTypeID)) + "..." : org.organizationShortName;
                }
                
                if (i > 2) {
                    org.displayName = org.prefix + " " + org.displayName;
                }


                if (org.signupEnable) {
                    org.visible = true;
                    org.enabled = true;
                } 
            });
            $scope.organizationTree.forEach(function (org) {
                if (!org.enabled) {
                    org.visible = $scope.anyChildrenAreEnabled(org.organizationID);
                }
            });

        }
        $scope.setOrganizationPath = function (organization) {
            organization.path = [];
            if (organization.parentOrganizationID != null) {
                $scope.organizationTree.forEach(function (parentOrg) {
                    if (parentOrg.organizationID == organization.parentOrganizationID) {
                        if (typeof parentOrg.path != "undefined" && parentOrg.path != null) {
                            organization.path = angular.copy(parentOrg.path);
                        }
                        if (organization.path.indexOf(organization.parentOrganizationID) == -1) {
                            organization.path.push(organization.parentOrganizationID);
                        }
                    }
                });
            }
            return organization.path;
        }
        $scope.anyChildrenAreEnabled = function (orgID) {
            var anyChildEnabled = false;
            $scope.organizationTree.forEach(function (org) {
                if (org.path.indexOf(orgID) > -1 && org.enabled && org.organizationTypeID > 1) {
                    anyChildEnabled = true;
                }
            });
            return anyChildEnabled;
        }


        $scope.selectOrganization = function (organizationID) {
            window.location.href = "/Account/signup?organizationID=" + organizationID;
        }

        $scope.notUnderBMW = function () {
            return function (org) {
                return $scope.bmwUnderOrgIDs.indexOf(org.key) == -1;
            };
        }

        $scope.orgIsEnabled = function (org) {
            return org.organizationTypeID > 1 && org.visible;
        }


    };

    // Set up dependecy injections for dependencies used by controller function
    signupController.$inject = ['$scope', '$state', '$sce', 'ModalConfirmService', 'CallApiService', 'CallRestApiService', '$http', 'ServerValues'];

    // Register routing and the controller
    angular.module('rubicApp')
        .config(function ($stateProvider, $urlRouterProvider) {

            $stateProvider

                // route to show our basic form (/form)
                .state('form', {
                    url: '/form',
                    templateUrl: '/app/viewapps/Signup/form.html',
                    controller: 'signupController'
                })

                // nested states 
                // each of these sections will have their own view
                // url will be nested (/form/profile)
                .state('form.profile', {
                    url: '/profile',
                    templateUrl: '/app/viewapps/Signup/form-profile.html'
                })

                // url will be /form/family
                .state('form.family', {
                    url: '/family',
                    templateUrl: '/app/viewapps/Signup/form-family.html'
                })

                // url will be /form/membership
                .state('form.membership', {
                    url: '/membership',
                    templateUrl: '/app/viewapps/Signup/form-membership.html'
                })

                // url will be /form/additions
                .state('form.additions', {
                    url: '/additions',
                    templateUrl: '/app/viewapps/Signup/form-additions.html'
                })

                // url will be /form/fields
                .state('form.fields', {
                    url: '/fields',
                    templateUrl: '/app/viewapps/Signup/form-fields.html'
                })

                // url will be /form/org
                .state('form.org', {
                    url: '/org',
                    templateUrl: '/app/viewapps/Signup/form-org.html'
                })

                // url will be /form/group
                .state('form.group', {
                    url: '/group',
                    templateUrl: '/app/viewapps/Signup/form-group.html'
                });

            // catch all route
            // send users to the form page 
            $urlRouterProvider.otherwise('/form/profile');
        })
        .controller('signupController', signupController);
}());
/**
 * Checklist-model
 * AngularJS directive for list of checkboxes
 * https://github.com/vitalets/checklist-model
 * License: MIT http://opensource.org/licenses/MIT
 */

//angular.module('checklist-model', [])
angular.module('rubicApp')
.directive('checklistModel', ['$parse', '$compile', function($parse, $compile) {
  // contains
  function contains(arr, item, comparator) {
    if (angular.isArray(arr)) {
      for (var i = arr.length; i--;) {
        if (comparator(arr[i], item)) {
          return true;
        }
      }
    }
    return false;
  }

  // add
  function add(arr, item, comparator) {
    arr = angular.isArray(arr) ? arr : [];
      if(!contains(arr, item, comparator)) {
          arr.push(item);
      }
    return arr;
  }  

  // remove
  function remove(arr, item, comparator) {
    if (angular.isArray(arr)) {
      for (var i = arr.length; i--;) {
        if (comparator(arr[i], item)) {
          arr.splice(i, 1);
          break;
        }
      }
    }
    return arr;
  }

  // http://stackoverflow.com/a/19228302/1458162
  function postLinkFn(scope, elem, attrs) {
     // exclude recursion, but still keep the model
    var checklistModel = attrs.checklistModel;
    attrs.$set("checklistModel", null);
    // compile with `ng-model` pointing to `checked`
    $compile(elem)(scope);
    attrs.$set("checklistModel", checklistModel);

    // getter / setter for original model
    var getter = $parse(checklistModel);
    var setter = getter.assign;
    var checklistChange = $parse(attrs.checklistChange);
    var checklistBeforeChange = $parse(attrs.checklistBeforeChange);

    // value added to list
    var value = attrs.checklistValue ? $parse(attrs.checklistValue)(scope.$parent) : attrs.value;


    var comparator = angular.equals;

    if (attrs.hasOwnProperty('checklistComparator')){
      if (attrs.checklistComparator[0] == '.') {
        var comparatorExpression = attrs.checklistComparator.substring(1);
        comparator = function (a, b) {
          return a[comparatorExpression] === b[comparatorExpression];
        };
        
      } else {
        comparator = $parse(attrs.checklistComparator)(scope.$parent);
      }
    }

    // watch UI checked change
    scope.$watch(attrs.ngModel, function(newValue, oldValue) {
      if (newValue === oldValue) { 
        return;
      } 

      if (checklistBeforeChange && (checklistBeforeChange(scope) === false)) {
        scope[attrs.ngModel] = contains(getter(scope.$parent), value, comparator);
        return;
      }

      setValueInChecklistModel(value, newValue);

      if (checklistChange) {
        checklistChange(scope);
      }
    });

    function setValueInChecklistModel(value, checked) {
      var current = getter(scope.$parent);
      if (angular.isFunction(setter)) {
        if (checked === true) {
          setter(scope.$parent, add(current, value, comparator));
        } else {
          setter(scope.$parent, remove(current, value, comparator));
        }
      }
      
    }

    // declare one function to be used for both $watch functions
    function setChecked(newArr, oldArr) {
      if (checklistBeforeChange && (checklistBeforeChange(scope) === false)) {
        setValueInChecklistModel(value, scope[attrs.ngModel]);
        return;
      }
      scope[attrs.ngModel] = contains(newArr, value, comparator);
    }

    // watch original model change
    // use the faster $watchCollection method if it's available
    if (angular.isFunction(scope.$parent.$watchCollection)) {
        scope.$parent.$watchCollection(checklistModel, setChecked);
    } else {
        scope.$parent.$watch(checklistModel, setChecked, true);
    }
  }

  return {
    restrict: 'A',
    priority: 1000,
    terminal: true,
    scope: true,
    compile: function(tElement, tAttrs) {
      if ((tElement[0].tagName !== 'INPUT' || tAttrs.type !== 'checkbox') && (tElement[0].tagName !== 'MD-CHECKBOX') && (!tAttrs.btnCheckbox)) {
        throw 'checklist-model should be applied to `input[type="checkbox"]` or `md-checkbox`.';
      }

      if (!tAttrs.checklistValue && !tAttrs.value) {
        throw 'You should provide `value` or `checklist-value`.';
      }

      // by default ngModel is 'checked', so we set it if not specified
      if (!tAttrs.ngModel) {
        // local scope var storing individual checkbox model
        tAttrs.$set("ngModel", "checked");
      }

      return postLinkFn;
    }
  };
}]);

