/* Minification failed. Returning unminified contents.
(10019,50-51): run-time error JS1195: Expected expression: .
(10019,55-56): run-time error JS1003: Expected ':': ;
(10020,24): run-time error JS1004: Expected ';'
(10020,66-67): run-time error JS1195: Expected expression: .
(10020,71-72): run-time error JS1003: Expected ':': ;
(13659,17-20): run-time error JS1009: Expected '}': ...
(13660,22): run-time error JS1004: Expected ';'
(13660,22-23): run-time error JS1195: Expected expression: :
(13661,21): run-time error JS1004: Expected ';'
(13661,21-22): run-time error JS1195: Expected expression: :
(13742,1-2): run-time error JS1006: Expected ')': }
(13742,1-2): run-time error JS1002: Syntax error: }
(13742,2-3): run-time error JS1195: Expected expression: )
(17151,42-43): run-time error JS1195: Expected expression: .
(17151,48-49): run-time error JS1195: Expected expression: .
(17151,80-81): run-time error JS1003: Expected ':': )
(17152,33-36): run-time error JS1009: Expected '}': var
(17152,33-36): run-time error JS1003: Expected ':': var
(17152,89-90): run-time error JS1006: Expected ')': ;
(17167,31-35): run-time error JS1006: Expected ')': else
(17167,30): run-time error JS1004: Expected ';'
(17172,26-27): run-time error JS1195: Expected expression: )
(17174,13-14): run-time error JS1006: Expected ')': }
(17173,18): run-time error JS1004: Expected ';'
(17174,14-15): run-time error JS1195: Expected expression: )
(19439,17-20): run-time error JS1009: Expected '}': ...
(19796,1-2): run-time error JS1006: Expected ')': }
(19796,1-2): run-time error JS1002: Syntax error: }
(19796,2-3): run-time error JS1195: Expected expression: )
(20196,17-20): run-time error JS1009: Expected '}': ...
(20555,1-2): run-time error JS1006: Expected ')': }
(20555,1-2): run-time error JS1002: Syntax error: }
(20555,2-3): run-time error JS1195: Expected expression: )
(21737,38-41): run-time error JS1009: Expected '}': ...
(21737,38-41): run-time error JS1006: Expected ')': ...
(21737,37): run-time error JS1004: Expected ';'
(21737,59): run-time error JS1004: Expected ';'
(21737,59-60): run-time error JS1195: Expected expression: :
(21737,88-89): run-time error JS1195: Expected expression: )
(21739,21-27): run-time error JS1006: Expected ')': return
(21738,22): run-time error JS1004: Expected ';'
(21743,14-15): run-time error JS1195: Expected expression: )
(21833,1-2): run-time error JS1006: Expected ')': }
(21833,1-2): run-time error JS1002: Syntax error: }
(21833,2-3): run-time error JS1195: Expected expression: )
(17152,37-41): run-time error JS1300: Strict-mode does not allow assignment to undefined variables: file
(10020,25-52): run-time error JS1300: Strict-mode does not allow assignment to undefined variables: hasIndividualPaymentMethods
 */
/*! 4.0.4 */
!function(){function a(a,b){window.XMLHttpRequest.prototype[a]=b(window.XMLHttpRequest.prototype[a])}function b(a,b,c,d,g,h){function i(){return"input"===b[0].tagName.toLowerCase()&&b.attr("type")&&"file"===b.attr("type").toLowerCase()}function j(b){if(!p){p=!0;try{for(var i=b.__files_||b.target&&b.target.files,j=[],k=[],l=0;l<i.length;l++){var m=i.item(l);f(a,g,c,m,b)?j.push(m):k.push(m)}e(g,h,a,d,c,o,j,k,b),0==j.length&&(b.target.value=j)}finally{p=!1}}}function k(d){c.ngfMultiple&&d.attr("multiple",g(c.ngfMultiple)(a)),g(c.ngfMultiple)(a)||d.attr("multiple",void 0),c.accept&&d.attr("accept",c.accept),c.ngfCapture&&d.attr("capture",g(c.ngfCapture)(a)),c.ngfDisabled&&d.attr("disabled",g(c.ngfDisabled)(a));for(var e=0;e<b[0].attributes.length;e++){var f=b[0].attributes[e];"type"!==f.name&&"class"!==f.name&&"id"!==f.name&&"style"!==f.name&&d.attr(f.name,f.value)}}function l(){if(!b.attr("disabled")){var a=angular.element('<input type="file">');return k(a),i()?(b.replaceWith(a),b=a):(a.css("display","none").attr("tabindex","-1").attr("__ngf_gen__",!0),b.__ngf_ref_elem__&&b.__ngf_ref_elem__.remove(),b.__ngf_ref_elem__=a,document.body.appendChild(a[0])),a}}function m(b){e(g,h,a,d,c,o,[],[],b,!0)}function n(a){function c(){d[0].click(),i()&&(b.bind("click touchend",n),a.preventDefault())}a.preventDefault();var d=l(a);d&&(d.bind("change",j),m(a),navigator.userAgent.toLowerCase().match(/android/)?setTimeout(function(){c()},0):c())}var o=c.ngfChange||c.ngfSelect&&c.ngfSelect.indexOf("(")>0,p=!1;window.FileAPI&&window.FileAPI.ngfFixIE?window.FileAPI.ngfFixIE(b,l,k,j,m):b.bind("click touchend",n)}function c(a,b,c,g,h,i,j){function k(a,b,c){var d=!0,e=c.dataTransfer.items;if(null!=e)for(var g=0;g<e.length&&d;g++)d=d&&("file"==e[g].kind||""==e[g].kind)&&f(a,h,b,e[g],c);var i=h(b.ngfDragOverClass)(a,{$event:c});return i&&(i.delay&&(q=i.delay),i.accept&&(i=d?i.accept:i.reject)),i||b.ngfDragOverClass||"dragover"}function l(b,d,e,g){function k(d){f(a,h,c,d,b)?m.push(d):n.push(d)}function l(a,b,c){if(null!=b)if(b.isDirectory){var d=(c||"")+b.name;k({name:b.name,type:"directory",path:d});var e=b.createReader(),f=[];p++;var g=function(){e.readEntries(function(d){try{if(d.length)f=f.concat(Array.prototype.slice.call(d||[],0)),g();else{for(var e=0;e<f.length;e++)l(a,f[e],(c?c:"")+b.name+"/");p--}}catch(h){p--,console.error(h)}},function(){p--})};g()}else p++,b.file(function(a){try{p--,a.path=(c?c:"")+a.name,k(a)}catch(b){p--,console.error(b)}},function(){p--})}var m=[],n=[],o=b.dataTransfer.items,p=0;if(o&&o.length>0&&"file"!=j.protocol())for(var q=0;q<o.length;q++){if(o[q].webkitGetAsEntry&&o[q].webkitGetAsEntry()&&o[q].webkitGetAsEntry().isDirectory){var r=o[q].webkitGetAsEntry();if(r.isDirectory&&!e)continue;null!=r&&l(m,r)}else{var s=o[q].getAsFile();null!=s&&k(s)}if(!g&&m.length>0)break}else{var t=b.dataTransfer.files;if(null!=t)for(var q=0;q<t.length&&(k(t.item(q)),g||!(m.length>0));q++);}var u=0;!function v(a){i(function(){if(p)10*u++<2e4&&v(10);else{if(!g&&m.length>1){for(q=0;"directory"==m[q].type;)q++;m=[m[q]]}d(m,n)}},a||0)}()}var m=d();if(c.dropAvailable&&i(function(){a[c.dropAvailable]?a[c.dropAvailable].value=m:a[c.dropAvailable]=m}),!m)return 1==h(c.ngfHideOnDropNotAvailable)(a)&&b.css("display","none"),void 0;var n,o=null,p=h(c.ngfStopPropagation),q=1,r=(h(c.ngfAccept),h(c.ngfDisabled));b[0].addEventListener("dragover",function(d){if(!r(a)){if(d.preventDefault(),p(a)&&d.stopPropagation(),navigator.userAgent.indexOf("Chrome")>-1){var e=d.dataTransfer.effectAllowed;d.dataTransfer.dropEffect="move"===e||"linkMove"===e?"move":"copy"}i.cancel(o),a.actualDragOverClass||(n=k(a,c,d)),b.addClass(n)}},!1),b[0].addEventListener("dragenter",function(b){r(a)||(b.preventDefault(),p(a)&&b.stopPropagation())},!1),b[0].addEventListener("dragleave",function(){r(a)||(o=i(function(){b.removeClass(n),n=null},q||1))},!1),b[0].addEventListener("drop",function(d){r(a)||(d.preventDefault(),p(a)&&d.stopPropagation(),b.removeClass(n),n=null,l(d,function(b,f){e(h,i,a,g,c,c.ngfChange||c.ngfDrop&&c.ngfDrop.indexOf("(")>0,b,f,d)},0!=h(c.ngfAllowDir)(a),c.multiple||h(c.ngfMultiple)(a)))},!1)}function d(){var a=document.createElement("div");return"draggable"in a&&"ondrop"in a}function e(a,b,c,d,e,f,g,h,i,j){function k(){d&&(a(e.ngModel).assign(c,g),b(function(){d&&d.$setViewValue(null!=g&&0==g.length?null:g)})),e.ngModelRejected&&a(e.ngModelRejected).assign(c,h),f&&a(f)(c,{$files:g,$rejectedFiles:h,$event:i})}j?k():b(function(){k()})}function f(a,b,c,d,e){var f=b(c.ngfAccept),h=b(c.ngfMaxSize)(a)||9007199254740991,i=b(c.ngfMinSize)(a)||-1,j=f(a,{$file:d,$event:e}),k=!1;if(null!=j&&angular.isString(j)){var l=new RegExp(g(j),"gi");k=null!=d.type&&d.type.match(l)||null!=d.name&&d.name.match(l)}return(null==j||k)&&(null==d.size||d.size<h&&d.size>i)}function g(a){if(a.length>2&&"/"===a[0]&&"/"===a[a.length-1])return a.substring(1,a.length-1);var b=a.split(","),c="";if(b.length>1)for(var d=0;d<b.length;d++)c+="("+g(b[d])+")",d<b.length-1&&(c+="|");else 0==a.indexOf(".")&&(a="*"+a),c="^"+a.replace(new RegExp("[.\\\\+*?\\[\\^\\]$(){}=!<>|:\\-]","g"),"\\$&")+"$",c=c.replace(/\\\*/g,".*").replace(/\\\?/g,".");return c}var h;window.XMLHttpRequest&&!window.XMLHttpRequest.__isFileAPIShim&&a("setRequestHeader",function(a){return function(b,c){if("__setXHR_"===b){var d=c(this);d instanceof Function&&d(this)}else a.apply(this,arguments)}});var i=angular.module("ngFileUpload",[]);i.version="4.0.4",i.service("Upload",["$http","$q","$timeout",function(a,b,c){function d(d){d.method=d.method||"POST",d.headers=d.headers||{},d.transformRequest=d.transformRequest||function(b,c){return window.ArrayBuffer&&b instanceof window.ArrayBuffer?b:a.defaults.transformRequest[0](b,c)};var e=b.defer(),f=e.promise;return d.headers.__setXHR_=function(){return function(a){a&&(d.__XHR=a,d.xhrFn&&d.xhrFn(a),a.upload.addEventListener("progress",function(a){a.config=d,e.notify?e.notify(a):f.progress_fn&&c(function(){f.progress_fn(a)})},!1),a.upload.addEventListener("load",function(a){a.lengthComputable&&(a.config=d,e.notify?e.notify(a):f.progress_fn&&c(function(){f.progress_fn(a)}))},!1))}},a(d).then(function(a){e.resolve(a)},function(a){e.reject(a)},function(a){e.notify(a)}),f.success=function(a){return f.then(function(b){a(b.data,b.status,b.headers,d)}),f},f.error=function(a){return f.then(null,function(b){a(b.data,b.status,b.headers,d)}),f},f.progress=function(a){return f.progress_fn=a,f.then(null,null,function(b){a(b)}),f},f.abort=function(){return d.__XHR&&c(function(){d.__XHR.abort()}),f},f.xhr=function(a){return d.xhrFn=function(b){return function(){b&&b.apply(f,arguments),a.apply(f,arguments)}}(d.xhrFn),f},f}this.upload=function(a){return a.headers=a.headers||{},a.headers["Content-Type"]=void 0,a.transformRequest=a.transformRequest?angular.isArray(a.transformRequest)?a.transformRequest:[a.transformRequest]:[],a.transformRequest.push(function(b){var c=new FormData,d={};for(h in a.fields)a.fields.hasOwnProperty(h)&&(d[h]=a.fields[h]);if(b&&(d.data=b),a.formDataAppender)for(h in d)d.hasOwnProperty(h)&&a.formDataAppender(c,h,d[h]);else for(h in d)if(d.hasOwnProperty(h)){var e=d[h];void 0!==e&&(angular.isDate(e)&&(e=e.toISOString()),angular.isString(e)?c.append(h,e):a.sendObjectsAsJsonBlob&&angular.isObject(e)?c.append(h,new Blob([e],{type:"application/json"})):c.append(h,JSON.stringify(e)))}if(null!=a.file){var f=a.fileFormDataName||"file";if(angular.isArray(a.file))for(var g=angular.isString(f),i=0;i<a.file.length;i++)c.append(g?f:f[i],a.file[i],a.fileName&&a.fileName[i]||a.file[i].name);else c.append(f,a.file,a.fileName||a.file.name)}return c}),d(a)},this.http=function(a){return d(a)}}]),i.directive("ngfSelect",["$parse","$timeout","$compile",function(a,c,d){return{restrict:"AEC",require:"?ngModel",link:function(e,f,g,h){b(e,f,g,h,a,c,d)}}}]),i.directive("ngfDrop",["$parse","$timeout","$location",function(a,b,d){return{restrict:"AEC",require:"?ngModel",link:function(e,f,g,h){c(e,f,g,h,a,b,d)}}}]),i.directive("ngfNoFileDrop",function(){return function(a,b){d()&&b.css("display","none")}}),i.directive("ngfDropAvailable",["$parse","$timeout",function(a,b){return function(c,e,f){if(d()){var g=a(f.ngfDropAvailable);b(function(){g(c),g.assign&&g.assign(c,!0)})}}}]),i.directive("ngfThumbnail",["$parse","$timeout",function(a,b){return{restrict:"AE",link:function(a,c,d){window.FileReader&&a.$watch(d.ngfThumbnail,function(a){a&&a.type.indexOf("image")>-1?b(function(){var d=new FileReader;d.readAsDataURL(a),d.onload=function(a){b(function(){c.attr("src",a.target.result)})}}):c.attr("src","")})}}}])}(),function(){function a(a,b){window.XMLHttpRequest.prototype[a]=b(window.XMLHttpRequest.prototype[a])}function b(a,b,c){try{Object.defineProperty(a,b,{get:c})}catch(d){}}function c(a){return"input"===a[0].tagName.toLowerCase()&&a.attr("type")&&"file"===a.attr("type").toLowerCase()}var d=function(){try{var a=new ActiveXObject("ShockwaveFlash.ShockwaveFlash");if(a)return!0}catch(b){if(void 0!=navigator.mimeTypes["application/x-shockwave-flash"])return!0}return!1};if(window.XMLHttpRequest&&!window.FormData||window.FileAPI&&FileAPI.forceLoad){var e=function(a){if(!a.__listeners){a.upload||(a.upload={}),a.__listeners=[];var b=a.upload.addEventListener;a.upload.addEventListener=function(c,d){a.__listeners[c]=d,b&&b.apply(this,arguments)}}};a("open",function(a){return function(b,c,d){e(this),this.__url=c;try{a.apply(this,[b,c,d])}catch(f){f.message.indexOf("Access is denied")>-1&&(this.__origError=f,a.apply(this,[b,"_fix_for_ie_crossdomain__",d]))}}}),a("getResponseHeader",function(a){return function(b){return this.__fileApiXHR&&this.__fileApiXHR.getResponseHeader?this.__fileApiXHR.getResponseHeader(b):null==a?null:a.apply(this,[b])}}),a("getAllResponseHeaders",function(a){return function(){return this.__fileApiXHR&&this.__fileApiXHR.getAllResponseHeaders?this.__fileApiXHR.getAllResponseHeaders():null==a?null:a.apply(this)}}),a("abort",function(a){return function(){return this.__fileApiXHR&&this.__fileApiXHR.abort?this.__fileApiXHR.abort():null==a?null:a.apply(this)}}),a("setRequestHeader",function(a){return function(b,c){if("__setXHR_"===b){e(this);var d=c(this);d instanceof Function&&d(this)}else this.__requestHeaders=this.__requestHeaders||{},this.__requestHeaders[b]=c,a.apply(this,arguments)}}),a("send",function(a){return function(){var c=this;if(arguments[0]&&arguments[0].__isFileAPIShim){var e=arguments[0],f={url:c.__url,jsonp:!1,cache:!0,complete:function(a,d){c.__completed=!0,!a&&c.__listeners.load&&c.__listeners.load({type:"load",loaded:c.__loaded,total:c.__total,target:c,lengthComputable:!0}),!a&&c.__listeners.loadend&&c.__listeners.loadend({type:"loadend",loaded:c.__loaded,total:c.__total,target:c,lengthComputable:!0}),"abort"===a&&c.__listeners.abort&&c.__listeners.abort({type:"abort",loaded:c.__loaded,total:c.__total,target:c,lengthComputable:!0}),void 0!==d.status&&b(c,"status",function(){return 0==d.status&&a&&"abort"!==a?500:d.status}),void 0!==d.statusText&&b(c,"statusText",function(){return d.statusText}),b(c,"readyState",function(){return 4}),void 0!==d.response&&b(c,"response",function(){return d.response});var e=d.responseText||(a&&0==d.status&&"abort"!==a?a:void 0);b(c,"responseText",function(){return e}),b(c,"response",function(){return e}),a&&b(c,"err",function(){return a}),c.__fileApiXHR=d,c.onreadystatechange&&c.onreadystatechange(),c.onload&&c.onload()},fileprogress:function(a){if(a.target=c,c.__listeners.progress&&c.__listeners.progress(a),c.__total=a.total,c.__loaded=a.loaded,a.total===a.loaded){var b=this;setTimeout(function(){c.__completed||(c.getAllResponseHeaders=function(){},b.complete(null,{status:204,statusText:"No Content"}))},FileAPI.noContentTimeout||1e4)}},headers:c.__requestHeaders};f.data={},f.files={};for(var g=0;g<e.data.length;g++){var h=e.data[g];null!=h.val&&null!=h.val.name&&null!=h.val.size&&null!=h.val.type?f.files[h.key]=h.val:f.data[h.key]=h.val}setTimeout(function(){if(!d())throw'Adode Flash Player need to be installed. To check ahead use "FileAPI.hasFlash"';c.__fileApiXHR=FileAPI.upload(f)},1)}else{if(this.__origError)throw this.__origError;a.apply(c,arguments)}}}),window.XMLHttpRequest.__isFileAPIShim=!0,window.FormData=FormData=function(){return{append:function(a,b,c){b.__isFileAPIBlobShim&&(b=b.data[0]),this.data.push({key:a,val:b,name:c})},data:[],__isFileAPIShim:!0}},window.Blob=Blob=function(a){return{data:a,__isFileAPIBlobShim:!0}},function(){if(window.FileAPI||(window.FileAPI={}),FileAPI.forceLoad&&(FileAPI.html5=!1),!FileAPI.upload){var a,b,c,e,f,g=document.createElement("script"),h=document.getElementsByTagName("script");if(window.FileAPI.jsUrl)a=window.FileAPI.jsUrl;else if(window.FileAPI.jsPath)b=window.FileAPI.jsPath;else for(c=0;c<h.length;c++)if(f=h[c].src,e=f.search(/\/ng\-file\-upload[\-a-zA-z0-9\.]*\.js/),e>-1){b=f.substring(0,e+1);break}null==FileAPI.staticPath&&(FileAPI.staticPath=b),g.setAttribute("src",a||b+"FileAPI.min.js"),document.getElementsByTagName("head")[0].appendChild(g),FileAPI.hasFlash=d()}}(),FileAPI.ngfFixIE=function(a,b,e,f){if(!d())throw'Adode Flash Player need to be installed. To check ahead use "FileAPI.hasFlash"';var g=function(){function d(a){var b,c;if(b=c=0,a.offsetParent)do b+=a.offsetLeft,c+=a.offsetTop;while(a=a.offsetParent);return{left:b,top:c}}if(a.attr("disabled"))a.__ngf_elem__.removeClass("js-fileapi-wrapper");else{var i=a.__ngf_elem__;i?e(a.__ngf_elem__):(i=a.__ngf_elem__=b(),i.addClass("js-fileapi-wrapper"),!c(a),setTimeout(function(){i.bind("mouseenter",g)},10),i.bind("change",function(a){h.apply(this,[a]),f.apply(this,[a])})),c(a)||i.css("position","absolute").css("top",d(a[0]).top+"px").css("left",d(a[0]).left+"px").css("width",a[0].offsetWidth+"px").css("height",a[0].offsetHeight+"px").css("filter","alpha(opacity=0)").css("display",a.css("display")).css("overflow","hidden").css("z-index","900000")}};a.bind("mouseenter",g);var h=function(a){for(var b=FileAPI.getFiles(a),c=0;c<b.length;c++)void 0===b[c].size&&(b[c].size=0),void 0===b[c].name&&(b[c].name="file"),void 0===b[c].type&&(b[c].type="undefined");a.target||(a.target={}),a.target.files=b,a.target.files!=b&&(a.__files_=b),(a.__files_||a.target.files).item=function(b){return(a.__files_||a.target.files)[b]||null}}},FileAPI.disableFileInput=function(a,b){b?a.removeClass("js-fileapi-wrapper"):a.addClass("js-fileapi-wrapper")}}window.FileReader||(window.FileReader=function(){var a=this,b=!1;this.listeners={},this.addEventListener=function(b,c){a.listeners[b]=a.listeners[b]||[],a.listeners[b].push(c)},this.removeEventListener=function(b,c){a.listeners[b]&&a.listeners[b].splice(a.listeners[b].indexOf(c),1)},this.dispatchEvent=function(b){var c=a.listeners[b.type];if(c)for(var d=0;d<c.length;d++)c[d].call(a,b)},this.onabort=this.onerror=this.onload=this.onloadstart=this.onloadend=this.onprogress=null;var c=function(b,c){var d={type:b,target:a,loaded:c.loaded,total:c.total,error:c.error};return null!=c.result&&(d.target.result=c.result),d},d=function(d){if(b||(b=!0,a.onloadstart&&a.onloadstart(c("loadstart",d))),"load"===d.type){a.onloadend&&a.onloadend(c("loadend",d));var e=c("load",d);a.onload&&a.onload(e),a.dispatchEvent(e)}else if("progress"===d.type){var e=c("progress",d);a.onprogress&&a.onprogress(e),a.dispatchEvent(e)}else{var e=c("error",d);a.onerror&&a.onerror(e),a.dispatchEvent(e)}};this.readAsArrayBuffer=function(a){FileAPI.readAsBinaryString(a,d)},this.readAsBinaryString=function(a){FileAPI.readAsBinaryString(a,d)},this.readAsDataURL=function(a){FileAPI.readAsDataURL(a,d)},this.readAsText=function(a){FileAPI.readAsText(a,d)}})}();;
var app = angular.module('MWPApp', ['pascalprecht.translate', 'ngSanitize', 'wbx-multifactor', 'isteven-multi-select', 'ui.router', 'ui.bootstrap', 'ngFileUpload', 'ngAria']);

bootstrapServiceBindings(app);

//Turn off debug mode to speed up production
//app.config(['$compileProvider', function ($compileProvider) {
//    $compileProvider.debugInfoEnabled(false);

//}]);

app.run(['$rootScope', function ($rootScope) {
    $("#mainContainer").show();
    $("#allContainer").show();

    $rootScope.$on('$translateChangeSuccess', function (event, data) {
        document.documentElement.setAttribute('lang', data.language);
    });

}]);


///* Add a broadcast service to exchange messages between ng controllers. 
//    See ProviderSearchCtrl.js and AddMemberCtrl.js for usage
//*/
app.factory('wbxProviderSearch', function ($rootScope) {

    var sharedService = {};

    sharedService.message = null;
    sharedService.prepForBroadcast = function (msg) {
        this.message = msg;
        this.broadcastItem();
    };

    sharedService.broadcastItem = function () {
        $rootScope.$broadcast('handleBroadcast');
    };

    return sharedService;
});



////This is only used in PWP. But because MWP is using the same Entity Management and this service is needed there, 
//// we have to inject it here too.
//app.service('WBXVerificationCountService', function () {
//    var verificationCount = 0;
//    return {
//        setVerificationCount: function (newCount) {
//            verificationCount = newCount;
//        },
//        getVerificationCount: function () {
//            return verificationCount;
//        },
//        increaseVerificationCount: function () {
//            verificationCount++;
//            return verificationCount;
//        },
//        decreaseVerificationCount: function () {
//            verificationCount--;
//            return verificationCount;
//        }
//    }
//});

if (typeof String.prototype.trim !== 'function') {
    String.prototype.trim = function () {
        return this.replace(/^\s+|\s+$/g, '');
    }
}

(function ($, window, i) {
    $.fn.mobileNav = function (options) {

        // Default settings
        var settings = $.extend({
            'active': 'selected', // String: Set the "active" class
            'header': '', // String: Specify text for "header" and show header instead of the active item
            'indent': '- ', // String: Specify text for indenting sub-items
            'label': '' // String: sets the <label> text for the <select> (if not set, no label will be added)
        }, options);

        return this.each(function () {

            // Used for namespacing
            i++;

            var $nav = $(this),
              // Namespacing
              namespace = 'mobile-nav',
              namespace_i = namespace + i,
              l_namespace_i = '.l_' + namespace_i,

              $select = $('<select/>').attr("id", namespace_i)
                .addClass(namespace + ' ' + namespace_i)
                .addClass("form-control");

            if ($nav.is('ul,ol')) {
                if (settings.header !== '') {
                    $select.append(
                      $('<option/>').text(settings.header)
                    );
                }

                // Build options
                var options = '';

                $nav
                  .addClass('l_' + namespace_i)
                  .find('a')
                  .each(function () {
                      options += '<option value="' + $(this).attr('href') + '">';
                      var j;
                      for (j = 0; j < $(this).parents('ul, ol').length - 1; j++) {
                          options += settings.indent;
                      }
                      options += $(this).text() + '</option>';
                  });

                // Append options into a select
                $select.append(options);

                $select.first().attr('selected', true);

                // Change window location
                $select.change(function () {
                    window.location.href = $(this).val();
                });

                // Inject select
                $(l_namespace_i).after($select);

                // Inject label
                if (settings.label) {
                    $select.before(
                      $("<label/>")
                        .attr("for", namespace_i)
                        .addClass(namespace + '_label ' + namespace_i + '_label')
                        .append(settings.label)
                    );
                }
            }

        });
    };
})(jQuery, this, 0);

$(document).ready(function () {
    $('.mobile-nav').mobileNav();
});

;
(function () {
    "use strict";
    app.directive('wbxAriaLiveIfIe', wbxAriaLiveIfIe);

    function wbxAriaLiveIfIe() {
        return {
            restrict: 'A',
            link: {
        	    post: function(scope, element, attributes){
                    var userAgent = window.navigator.userAgent;
                    var isIE = /MSIE|Trident|Edge\//.test(userAgent);

                    if (isIE) {
                        angular.element(element).attr('aria-live','polite');
                    }
	            }
            }
        };
    }

})();;
(function () {
    "use strict";
    app.directive('wbxFormWithErrorBanner', wbxInputLabelKeyDirective);

    function wbxInputLabelKeyDirective() {
        return {
            restrict: 'A',
            link: function (scope, element, attributes) {
                setTimeout(function () {
                    let controlsArray = [];
                    const formName = attributes.name.split(".");
                    const labels = _.chain(element.find("label"))
                        .filter(function(item){return item.attributes["data-translation-key"] != undefined})
                        .map( function (item) {
                        let wbxValidationTextElement = angular.element(item.parentElement).find("wbx-validation-text")[0];
                        let haswbxValidationTextElement = wbxValidationTextElement != undefined;
                        let overrideValidationText = haswbxValidationTextElement ? wbxValidationTextElement.attributes["override-error-list"] : undefined;
                        let hasOverrideValidationText = overrideValidationText != undefined;

                        return {
                            overrideValidations: hasOverrideValidationText ? overrideValidationText.value : undefined,
                            inputId: item.attributes.for.value,
                            text: item.attributes["data-translation-key"].value
                        }
                    });
                    labels.forEach(function (item) {
                        if (scope.vm[formName[1]][item.inputId] == null) return;
                        scope.vm[formName[1]][item.inputId].wbxLabelKey = item.text;
                        scope.vm[formName[1]][item.inputId].wbxOverrideValidations = item.overrideValidations;
                        controlsArray.push(item.inputId)
                    })
                    scope.vm[formName[1]].controlsList = controlsArray;
                }, 500)
            }
        };
    }

})();;
/* Mask Directives -  Written with minification support, 
see 1. )http://odetocode.com/blogs/scott/archive/2013/03/13/angularjs-controllers-dependencies-and-minification.aspx 
    2.) http://blog.getbrandid.com/2013/03/22/your-angular-js-directives-will-break-when-minified-this-is-how-you-write-directives-likeaboss/
*/

app.directive('wbxDateMask', ["$parse", "$timeout", function ($parse, $timeout) {
    return function (scope, element, attrs) {
        var ngModel = $parse(attrs.ngModel);

        $timeout(function () {
            var date = moment(element.val());

            if (date.isValid()) {
                element.val(date.format("MM/DD/YYYY"));
            }

            element.inputmask("mm/dd/yyyy",
                {
                    yearrange: { minyear: 1900, maxyear: 2078 },
                    clearIncomplete: true,
                    oncomplete: function () {
                        scope.$apply(function (scope) {
                            // Change binded variable
                            ngModel.assign(scope, element.val());
                        });
                    },
                    onincomplete: function () {
                        scope.$apply(function (scope) {
                            // Change binded variable
                            ngModel.assign(scope, '');
                        });
                    },
                    oncleared: function () {
                        scope.$apply(function (scope) {
                            // Change binded variable
                            ngModel.assign(scope, '');
                        });
                    }
                });
        });
    }
}]);

app.directive('wbxDateMaskMmyyyy', ["$parse", function ($parse) {
    return function (scope, element, attrs) {
        var ngModel = $parse(attrs.ngModel);
        element.inputmask("mm/yyyy",
            {
                yearrange: { minyear: 1900, maxyear: 2078 },
                clearIncomplete: true,
                oncomplete: function () {
                    scope.$apply(function (scope) {
                        // Change binded variable

                        ngModel.assign(scope, element.val());
                    });
                },
                onincomplete: function () {
                    scope.$apply(function (scope) {
                        // Change binded variable
                        ngModel.assign(scope, '');
                    });
                },
                oncleared: function () {
                    scope.$apply(function (scope) {
                        // Change binded variable
                        ngModel.assign(scope, '');
                    });
                }
            });
    }
}]);

app.directive('wbxTimeMask', ["$parse",
    function ($parse) {
        var link = function ($scope, $element, $attrs, ngModel) {
            var assess = function (scope, element, attrs, viewValue) {
                var ngModel = $parse($attrs.ngModel);
                element.inputmask("h:s t",
                    {
                        oncleared: function () {
                            scope.$apply(function (scope) {
                                // Change binded variable
                                ngModel.assign(scope, null);
                            });
                        }
                    });

                return viewValue;
            };

            ngModel.$parsers.unshift(function (viewValue) {
                return assess($scope, $element, $attrs, viewValue);
            });

            ngModel.$formatters.push(function (viewValue) {
                var dateMoment = moment(viewValue, moment.ISO_8601);
                var timeString = viewValue; //If it's not ISO8601, just pass it through
                if (dateMoment.isValid()) {
                    timeString = dateMoment.format("hh:mm a");
                }
                return assess($scope, $element, $attrs, timeString);
            });

            $attrs.$observe('wbxTimeMask', function (comparisonModel) {
                // Whenever the comparison model changes we'll re-validate
                return assess($scope, $element, $attrs, ngModel.$viewValue);
            });

        };

        return {
            require: 'ngModel',
            link: link
        };

    }
]);

app.directive('wbxAlphaNumericMask', ["$parse", function ($parse) {
    return function (scope, element, attrs) {
        var ngModel = $parse(attrs.ngModel);
        element.inputmask("*{0,}",
            {
                placeholder: "",
                oncomplete: function () {
                    scope.$apply(function (scope) {
                        // Change binded variable
                        ngModel.assign(scope, element.val());
                    });
                },
                oncleared: function () {
                    scope.$apply(function (scope) {
                        // Change binded variable
                        ngModel.assign(scope, '');
                    });
                }
            });
    }
}]);

app.directive('wbxAlphaNumericNoSpecialCharsMask', ["$parse", function ($parse) {
    return function (scope, element, attrs) {
        var ngModel = $parse(attrs.ngModel);
        element.inputmask("Regex",
            {
                placeholder: "",
                regex: attrs.wbxRegex, //Define what's allowed for the alpha-numeric characters
                oncomplete: function () {
                    scope.$apply(function (scope) {
                        // Change binded variable
                        ngModel.assign(scope, element.val());
                    });
                },
                oncleared: function () {
                    scope.$apply(function (scope) {
                        // Change binded variable
                        ngModel.assign(scope, '');
                    });
                }
            });
    }
}]);

// for numbers with max length can use this mask
//example wbx-max-numeric-mask ="" and must have maxlength wbx-max-length ="whatever is maxlength"
app.directive('wbxMaxNumericMask', ["$parse", function ($parse) {
    return function (scope, element, attrs) {
        var ngModel = $parse(attrs.ngModel);
        element.inputmask("9{0," + attrs.wbxMaxLength + "}",
            {
                placeholder: "",
                oncomplete: function () {
                    scope.$apply(function (scope) {
                        // Change binded variable
                        ngModel.assign(scope, element.val());
                    });
                },
                oncleared: function () {
                    scope.$apply(function (scope) {
                        // Change binded variable
                        ngModel.assign(scope, element.val());
                    });
                }
            });
    }
}]);

//with combination of wbxNumericMask and maxlength there is an issue.
app.directive('wbxNumericMask', ["$parse", function ($parse) {
    return function (scope, element, attrs) {
        var ngModel = $parse(attrs.ngModel);
        element.inputmask(attrs.wbxNumericType != null ? attrs.wbxNumericType.toLowerCase() : "integer",
            {
                digits: (attrs.wbxNumericType != null && attrs.wbxNumericType.toLowerCase() == "decimal") ? attrs.wbxDigits != null ? attrs.wbxDigits : 2 : "*",
                max: attrs.wbxNumericMaxValue,
                min: attrs.wbxNumericMinValue,
                allowMinus: attrs.wbxNumericAllowMinus != null ? attrs.wbxNumericAllowMinus.toLowerCase() == "true" : false,
                radixFocus: false,
                allowPlus: false,
                rightAlign: !attrs.wbxIsLeftAligned,
                oncomplete: function () {
                    scope.$apply(function (scope) {
                        // Change binded variable
                        ngModel.assign(scope, element.val());
                    });
                },
                oncleared: function () {
                    scope.$apply(function (scope) {
                        // Change binded variable
                        ngModel.assign(scope, '');
                    });
                }
            });
    }
}]);

app.directive('wbxCurrencyMask', ["$filter", "$parse",
    function ($filter, $parse) {
        var link = function ($scope, $element, $attrs, ngModel) {
            var assess = function (scope, element, attrs, viewValue) {
                var ngModel = $parse(attrs.ngModel);
                element.inputmask("currency",
                    {
                        prefix: "",
                        //placeholder: "",  //If this is used, oncleared isn't fired when textbox is cleared. Don't use this.
                        radixFocus: false,
                        max: attrs.wbxCurrencyMaxValue,
                        allowMinus: attrs.wbxCurrencyAllowMinus != null ? attrs.wbxCurrencyAllowMinus.toLowerCase() == "true" : false,
                        digits: attrs.wbxCurrencyDecimalPoints,
                        clearMaskOnLostFocus: true, //This is so that the 0.00 doesn't show if the value hasn't been entered
                        autoUnmask: true, //This is what caused the 0.00 to work (0.00 being saved instead of "")
                        oncleared: function () {
                            scope.$apply(function (scope) {
                                // Change binded variable
                                ngModel.assign(scope, null); //This is to make sure that if there's nothing entered, the value will be null. instead of ""
                            });
                        }
                    });

                return viewValue;
            };

            ngModel.$parsers.unshift(function (viewValue) {
                var plainNumber = "";
                if (!isNaN(viewValue)) {
                    plainNumber = viewValue.replace(/[^\d|\-+|\.+]/g, '');
                }
                return plainNumber;
            });

            ngModel.$formatters.push(function (viewValue) {
                return assess($scope, $element, $attrs, viewValue);
            });

            $attrs.$observe('wbxCurrencyMaxValue', function (comparisonModel) {
                // Whenever the comparison model changes we'll re-validate
                return assess($scope, $element, $attrs, ngModel.$viewValue);
            });

        };

        return {
            require: 'ngModel',
            link: link
        };

    }
]);

app.directive('wbxSsnMask', ["$parse", function ($parse) {
    return function (scope, element, attrs) {
        var ngModel = $parse(attrs.ngModel);
        element.inputmask("999-99-9999",
            {
                clearIncomplete: true,
                oncomplete: function () {
                    scope.$apply(function (scope) {
                        // Change binded variable
                        ngModel.assign(scope, element.val());
                    });
                },
                oncleared: function () {
                    scope.$apply(function (scope) {
                        // Change binded variable
                        ngModel.assign(scope, '');
                    });
                }
            });
    }
}]);

app.directive('wbxPhoneMask', ["$parse",
    function ($parse) {
        var link = function ($scope, $element, $attrs, ngModel) {
            var assess = function (scope, element, attrs, viewValue) {
                var ngModel = $parse($attrs.ngModel);
                element.inputmask("(999) 999-9999",
                    {
                        clearIncomplete: true,
                        oncleared: function () {
                            scope.$apply(function (scope) {
                                // Change binded variable
                                ngModel.assign(scope, null);
                            });
                        }
                    });

                return viewValue;
            };

            ngModel.$parsers.unshift(function (viewValue) {
                if ((viewValue.replace(/([-~!@#$%^&*()_+=`{}\[\]\|\\:;'<>,.\/? ])+/g, '')).length === 10) {
                    return viewValue.replace(/\s/g, '');
                }
                else {
                    return viewValue;
                }
            });

            ngModel.$formatters.push(function (viewValue) {
                return assess($scope, $element, $attrs, viewValue);
            });

            $attrs.$observe('wbxPhoneMask', function (comparisonModel) {
                // Whenever the comparison model changes we'll re-validate
                return assess($scope, $element, $attrs, ngModel.$viewValue);
            });

        };

        return {
            require: 'ngModel',
            link: link
        };

    }
]);


app.directive('wbxPhoneMaskAllowAsterisks', ["$parse", function ($parse) {
    return function (scope, element, attrs) {
        var ngModel = $parse(attrs.ngModel);
        element.inputmask("(999) 999-9999",
            {
                definitions: {
                    "9": {
                        validator: "[0-9\*]",
                        cardinality: 1,
                        definitionSymbol: "*"
                    }
                },
                onKeyDown: function (event) {
                    if (event.key === "*") {
                        event.key = "";
                        event.preventDefault();
                    }
                },
                oncomplete: function () {
                    scope.$apply(function (scope) {
                        // Change binded variable
                        ngModel.assign(scope, element.val().replace(/\s/g, ''));
                    });
                },
                oncleared: function () {
                    scope.$apply(function (scope) {
                        // Change binded variable
                        ngModel.assign(scope, '');
                    });
                }
            });
    }
}]);

//This is to accomodate android mobile devices that's not working well with robinherbots input mask
app.directive('wbxAndroidDateMask', [function () {
    return {
        restrict: 'A',
        link: function (scope, element, attrs) {
            if (navigator.userAgent.match(/Android/i)) {
                element.bind('keyup',
                    function (event) {
                        var id = attrs.id;
                        var inputText = document.getElementById(id).value;
                        if (inputText.substring(0, 1) != "m" &&
                            inputText.substring(1, 2) != "m" &&
                            inputText.substring(3, 4) != "d") {
                            if (inputText.substring(4, inputText.length) == "d/yyyy") {
                                setCaretPosition(element[0], 4);
                            } else if (inputText.substring(4, 5) != "d" &&
                                inputText.substring(6, 7) != "y" &&
                                inputText.substring(7, inputText.length) == "yyy") {
                                setCaretPosition(element[0], 7);
                            }
                        }
                    });
            }
        }
    };

    function setCaretPosition(elem, caretPos) {
        if (elem !== null) {
            if (elem.createTextRange) {
                var range = elem.createTextRange();
                range.move('character', caretPos);
                range.select();
            } else {
                if (elem.setSelectionRange) {
                    elem.focus();
                    elem.setSelectionRange(caretPos, caretPos);
                } else
                    elem.focus();
            }
        }
    }
}]);

//This is to accomodate android mobile devices that's not working well with robinherbots input mask
app.directive('wbxAndroidPhoneMask', [function () {
    return {
        restrict: 'A',
        link: function (scope, element, attrs) {
            if (navigator.userAgent.match(/Android/i)) {
                element.bind('keyup',
                    function (event) {
                        var id = attrs.id;
                        var inputText = document.getElementById(id).value;
                        if (inputText.substring(0, 2) != "(_" && inputText.substring(2, 3) != "_" && inputText.substring(3, 6) != "_) " && inputText.substring(6, 7) != "_") {
                            if (inputText.substring(7, inputText.length) == "__-____") {
                                setCaretPosition(element[0], 7);
                            } else if (inputText.substring(7, 8) != "_" && inputText.substring(8, 10) != "_-" && inputText.substring(10, 11) != "_" && inputText.substring(11, inputText.length) == "___") {
                                setCaretPosition(element[0], 11);
                            }
                        }
                    });
            }
        }
    };

    function setCaretPosition(elem, caretPos) {
        if (elem !== null) {
            if (elem.createTextRange) {
                var range = elem.createTextRange();
                range.move('character', caretPos);
                range.select();
            } else {
                if (elem.setSelectionRange) {
                    elem.focus();
                    elem.setSelectionRange(caretPos, caretPos);
                } else
                    elem.focus();
            }
        }
    }
}]);

//This is to accomodate android mobile devices that's not working well with robinherbots input mask
app.directive('wbxAndroidSsnMask', [function () {
    return {
        restrict: 'A',
        link: function (scope, element, attrs) {
            if (navigator.userAgent.match(/Android/i)) {
                element.bind('keyup',
                    function (event) {
                        var id = attrs.id;
                        var inputText = document.getElementById(id).value;
                        if (inputText.substring(0, 1) != "_" && inputText.substring(1, 2) != "_" && inputText.substring(2, 4) != "_-" && inputText.substring(4, 5) != "_") {
                            if (inputText.substring(5, inputText.length) == "_-____") {
                                setCaretPosition(element[0], 5);
                            } else if (inputText.substring(5, 7) != "_-" && inputText.substring(7, 8) != "_" && inputText.substring(8, inputText.length) == "___") {
                                setCaretPosition(element[0], 8);
                            }
                        }
                    });
            }
        }
    };

    function setCaretPosition(elem, caretPos) {
        if (elem !== null) {
            if (elem.createTextRange) {
                var range = elem.createTextRange();
                range.move('character', caretPos);
                range.select();
            } else {
                if (elem.setSelectionRange) {
                    elem.focus();
                    elem.setSelectionRange(caretPos, caretPos);
                } else
                    elem.focus();
            }
        }
    }
}]);

app.directive('wbxEinMask', ["$parse", function ($parse) {
    return function (scope, element, attrs) {
        var ngModel = $parse(attrs.ngModel);
        element.inputmask("99-9999999",
            {
                oncomplete: function () {
                    scope.$apply(function (scope) {
                        // Change binded variable
                        ngModel.assign(scope, element.val());
                    });
                },
                oncleared: function () {
                    scope.$apply(function (scope) {
                        // Change binded variable
                        ngModel.assign(scope, '');
                    });
                }
            });
    }
}]);


/*
     * this directive can be used for filename inputs.
     * it will limit the entry of characters to be alpha-numeric but in addition, it will allow certain special characters that are
     * allowed by Microsoft as a file name
*/

app.directive('wbxFilenameMask', ["$parse", function ($parse) {
    return function (scope, element, attrs) {
        var ngModel = $parse(attrs.ngModel);
        element.inputmask("Regex",
            {
                placeholder: "",
                regex: "[0-9A-Za-z!#$%&+=^_`{}~-]*", //define what's allowed for the alpha-numeric characters
                repeat: attrs.wbxMaxLength,
                oncomplete: function () {
                    scope.$apply(function (scope) {
                        // Change binded variable
                        ngModel.assign(scope, element.val());
                    });
                },
                oncleared: function () {
                    scope.$apply(function (scope) {
                        // Change binded variable
                        ngModel.assign(scope, '');
                    });
                }
            });
    };
}]);

app.directive('wbxRoutingNumber', ["$parse", function ($parse) {
    return function (scope, element, attrs) {
        var ngModel = $parse(attrs.ngModel);
        element.inputmask("999999999",
            {
                placeholder: "",
                clearIncomplete: false,
                oncomplete: function () {
                    scope.$apply(function (scope) {
                        // Change binded variable
                        ngModel.assign(scope, element.val());
                    });
                },
                oncleared: function () {
                    scope.$apply(function (scope) {
                        // Change binded variable
                        ngModel.assign(scope, '');
                    });
                }
            });
    }
}]);

app.directive('wbxAccountNumber', ["$parse", function ($parse) {
    return function (scope, element, attrs) {
        var ngModel = $parse(attrs.ngModel);
        element.inputmask("9{9,17}",
            {
                placeholder: "",
                clearIncomplete: false,
                oncomplete: function () {
                    scope.$apply(function (scope) {
                        // Change binded variable
                        ngModel.assign(scope, element.val());
                    });
                },
                oncleared: function () {
                    scope.$apply(function (scope) {
                        // Change binded variable
                        ngModel.assign(scope, '');
                    });
                }
            });
    }
}]);

/**
 * Above this line, ES and Portals are exactly the same. If any is changed, make sure it's sync'd up
 */

/**
 * Different between ES and Portals. Reassess if this can be consolidated
 */

/**
 * Only used in Portals (reassess if ES needs it as well)
 */



/**
 * Will be deprecated
 */

//Use wbxCurrencyMask instead
app.directive('currencyMask', ["$parse", function ($parse) {
    return function (scope, element, attrs, modelCtrl) {
        var ngModel = $parse(attrs.ngModel);

        var decimalPlaces = 2;
        if (angular.isDefined(attrs.currencyDecimalPlaces))
            decimalPlaces = attrs.currencyDecimalPlaces;

        var currencySeparator = '';
        if (angular.isDefined(attrs.currencySeparator))
            currencySeparator = attrs.currencySeparator;

        element.autoNumeric('init', { aSep: currencySeparator, mDec: decimalPlaces });
        element.css("text-align", "right");


        ////ngModel.$parsers.unshift(validate);
        //ngModel.$parsers.push(function (data) {
        //    //return $filter('number')(data, decimalPlaces);
        //    return data.replace(currencySeparator, '');
        //});

        //ngModel.$formatters.push(function (data) {
        //    return $filter('number')(data, decimalPlaces);
        //    //return data.replace(currencySeparator, '');
        //});

        //var val = element.val();

        element.keyup(function () {
            scope.$apply(function (scope) {
                // Change binded variable
                var val = element.val();
                ngModel.assign(scope, val);
            });
        });

        element.focusout(function () {
            var val = element.val();
        });

    }
}]);

app.directive('wbxSsnMaskOld', ["$parse", function ($parse) {
    return function (scope, element, attrs) {
        var ngModel = $parse(attrs.ngModel);
        element.inputmask("999-99-9999",
            {
                clearIncomplete: true,
                oncomplete: function () {
                    scope.$apply(function (scope) {
                        // Change binded variable
                        ngModel.assign(scope, element.val());
                    });
                },
                oncleared: function () {
                    scope.$apply(function (scope) {
                        // Change binded variable
                        ngModel.assign(scope, '');
                    });
                }
            });
    }
}]);

app.directive('wbxPhoneMaskOld', ["$parse",
    function ($parse) {
        var link = function ($scope, $element, $attrs, ngModel) {
            var assess = function (scope, element, attrs, viewValue) {
                var ngModel = $parse($attrs.ngModel);
                element.inputmask("(999) 999-9999",
                    {
                        clearIncomplete: true,
                        oncleared: function () {
                            scope.$apply(function (scope) {
                                // Change binded variable
                                ngModel.assign(scope, null);
                            });
                        }
                    });

                return viewValue;
            };

            ngModel.$parsers.unshift(function (viewValue) {
                if ((viewValue.replace(/([-~!@#$%^&*()_+=`{}\[\]\|\\:;'<>,.\/? ])+/g, '')).length === 10) {
                    return viewValue.replace(/\s/g, '');
                }
                else {
                    return viewValue;
                }
            });

            ngModel.$formatters.push(function (viewValue) {
                return assess($scope, $element, $attrs, viewValue);
            });

            $attrs.$observe('wbxPhoneMask', function (comparisonModel) {
                // Whenever the comparison model changes we'll re-validate
                return assess($scope, $element, $attrs, ngModel.$viewValue);
            });

        };

        return {
            require: 'ngModel',
            link: link
        };

    }
]);

app.directive('wbxZipMaskOld', ["$parse", function ($parse) {
    return function (scope, element, attrs) {
        var ngModel = $parse(attrs.ngModel);
        element.inputmask("99999",
            {
                placeholder: "",
                clearIncomplete: true,
                oncomplete: function () {
                    scope.$apply(function (scope) {
                        // Change binded variable
                        ngModel.assign(scope, element.val());
                    });
                },
                onincomplete: function () {
                    scope.$apply(function (scope) {
                        // Change binded variable
                        ngModel.assign(scope, '');
                    });
                },
                oncleared: function () {
                    scope.$apply(function (scope) {
                        // Change binded variable
                        ngModel.assign(scope, '');
                    });
                }
            });
    }
}]);

app.directive('wbxZipFourMaskOld', ["$parse", function ($parse) {
    return function (scope, element, attrs) {
        var ngModel = $parse(attrs.ngModel);
        element.inputmask("9999",
            {
                placeholder: "",
                clearIncomplete: true,
                oncomplete: function () {
                    scope.$apply(function (scope) {
                        // Change binded variable
                        ngModel.assign(scope, element.val());
                    });
                },
                onincomplete: function () {
                    scope.$apply(function (scope) {
                        // Change binded variable
                        ngModel.assign(scope, '');
                    });
                },
                oncleared: function () {
                    scope.$apply(function (scope) {
                        // Change binded variable
                        ngModel.assign(scope, '');
                    });
                }
            });
    }
}]);

//Use wbxMaxNumericMask instead
app.directive('wbxEntityIdMask', ["$parse", function ($parse) {
    return function (scope, element, attrs) {
        var ngModel = $parse(attrs.ngModel);
        element.inputmask("integer",
            {
                rightAlign: false,
                allowMinus: false,
                allowPlus: false,
                oncomplete: function () {
                    scope.$apply(function (scope) {
                        // Change binded variable
                        ngModel.assign(scope, element.val());
                    });
                },
                oncleared: function () {
                    scope.$apply(function (scope) {
                        // Change binded variable
                        ngModel.assign(scope, '');
                    });
                }
            });
    }
}]);

//Use wbxMaxNumericMask instead
app.directive('wbxFournumberMask', ["$parse", function ($parse) {
    return function (scope, element, attrs) {
        var ngModel = $parse(attrs.ngModel);
        element.inputmask("9999",
            {
                placeholder: "",
                clearIncomplete: false,
                oncomplete: function () {
                    scope.$apply(function (scope) {
                        // Change binded variable
                        ngModel.assign(scope, element.val());
                    });
                },
                oncleared: function () {
                    scope.$apply(function (scope) {
                        // Change binded variable
                        ngModel.assign(scope, '');
                    });
                }
            });
    }
}]);

//Use wbxMaxNumericMask instead
app.directive('wbxZipMask', ["$parse", function ($parse) {
    return function (scope, element, attrs) {
        var ngModel = $parse(attrs.ngModel);
        element.inputmask("99999",
            {
                placeholder: "",
                oncomplete: function () {
                    scope.$apply(function (scope) {
                        // Change binded variable
                        ngModel.assign(scope, element.val());
                    });
                },
                oncleared: function () {
                    scope.$apply(function (scope) {
                        // Change binded variable
                        ngModel.assign(scope, '');
                    });
                }
            });
    }
}]);

//Use wbxMaxNumericMask instead
app.directive('wbxZipFourMask', ["$parse", function ($parse) {
    return function (scope, element, attrs) {
        var ngModel = $parse(attrs.ngModel);
        element.inputmask("9999",
            {
                placeholder: "",
                oncomplete: function () {
                    scope.$apply(function (scope) {
                        // Change binded variable
                        ngModel.assign(scope, element.val());
                    });
                },
                oncleared: function () {
                    scope.$apply(function (scope) {
                        // Change binded variable
                        ngModel.assign(scope, '');
                    });
                }
            });
    }
}]);

//Use wbxMaxNumericMask instead
app.directive('wbxNpiMask', ["$parse", function ($parse) {
    return function (scope, element, attrs) {
        var ngModel = $parse(attrs.ngModel);
        element.inputmask("9999999999",
            {
                placeholder: "",
                oncomplete: function () {
                    scope.$apply(function (scope) {
                        // Change binded variable
                        ngModel.assign(scope, element.val());
                    });
                },
                oncleared: function () {
                    scope.$apply(function (scope) {
                        // Change binded variable
                        ngModel.assign(scope, '');
                    });
                }
            });
    }
}]);

//Use wbxMaxNumericMask instead
app.directive('wbxMemberIdMask', ["$parse", function ($parse) {
    return function (scope, element, attrs) {
        var ngModel = $parse(attrs.ngModel);
        element.inputmask("99",
            {
                placeholder: "",
                oncomplete: function () {
                    scope.$apply(function (scope) {
                        // Change binded variable
                        ngModel.assign(scope, element.val());
                    });
                },
                onBeforePaste: function (pastedValue, opts) {
                    scope.$apply(function (scope) {
                        // Change binded variable
                        ngModel.assign(scope, pastedValue);
                    });
                }
            });
    }
}]);

//Use wbxMaxNumericMask instead
app.directive('wbxPhoneExtensionMask', ["$parse", function ($parse) {
    return function (scope, element, attrs) {
        var ngModel = $parse(attrs.ngModel);
        element.inputmask("99999",
            {
                placeholder: "",
                oncomplete: function () {
                    scope.$apply(function (scope) {
                        // Change binded variable
                        ngModel.assign(scope, element.val());
                    });
                },
                oncleared: function () {
                    scope.$apply(function (scope) {
                        // Change binded variable
                        ngModel.assign(scope, '');
                    });
                }
            });
    }
}]);

app.directive('wbxCardNumberMask', ["$parse", function () {
    return function (scope, element) {
        element.inputmask("9999 9999 9999 9999", { placeholder: '' });
    }
}]);

app.directive('wbxDateMaskMmyy', ["$parse", function () {
    return function (scope, element) {
        element.inputmask("99/99", { placeholder: '' });
    }
}]);

app.directive('wbxCvcMask', ["$parse", function () {
    return function (scope, element) {
        element.inputmask("9999", { placeholder: '' });
    }
}]);

app.directive('wbxAccountNumberMask', ["$parse", function () {
    return function (scope, element) {
        element.inputmask("99999999999999999999", { placeholder: '' });
    }
}]);;
(function () {
    'use strict';
    app.directive('wbxSsnMaskNew', ssnMask);
    ssnMask.$inject = ['$parse'];

    function ssnMask($parse) {
        var directive = {
            link: link,
            controller: ssnMaskController,
            restrict: 'A',
            scope: {
                wbxSsnMaskNew: '=?'
            }
        };

        function link(scope, element, attrs) {
            scope.applyMask = function () {
                var ngModel = $parse(attrs.ngModel);
                element.inputmask("999-99-9999",
                    {
                        oncomplete: function () {
                            scope.$apply(function (scope) {
                                // Change binded variable
                                ngModel.assign(scope, element.val());
                            });
                        },
                        oncleared: function () {
                            scope.$apply(function (scope) {
                                // Change binded variable
                                ngModel.assign(scope, '');
                            });
                        }
                    });
            }

            scope.removeMask = function () {
                element.inputmask('remove');
            }
        }

        return directive;
    }

    ssnMaskController.$inject = ['$scope'];
    function ssnMaskController($scope) {
        $scope.$watch('wbxSsnMaskNew', function (n, o) {
            if (n != false) {
                $scope.applyMask();
            }
            else {
                $scope.removeMask();
            }
        });
    }

})();;
app.directive('wbxValidationMessage', function () {
    return {
        restrict: 'A',
        priority: 1000,
        require: '^wbxValidationTooltip',
        link: function (scope, element, attr, ctrl) {
            ctrl.$addExpression(attr.ngIf || true);
        }
    };
});

app.directive('wbxValidationTooltip', ['$timeout', function ($timeout) {
    return {
        restrict: 'E',
        transclude: true,
        require: '^form',
        scope: {
            tooltipPlacement: '=?',
            customErrorList: '<?'
        },

        template: '<div class="wbx-alert-icon fa fa-caret-left fa-lg" ng-show="errorCount > 0"></div>',

        controller: ['$scope', function ($scope) {
            var expressions = [];
            $scope.errorCount = 0;

            this.$addExpression = function (expr) {
                expressions.push(expr);
            };
            $scope.$watch(function () {
                var count = 0;
                angular.forEach(expressions, function (expr) {
                    ++count;
                });
                return count;

            }, function (newVal) {
                $scope.errorCount = newVal;
            });

        }],
        link: function (scope, element, attr, formController, transcludeFn) {
            scope.$form = formController;
            if (scope.tooltipPlacement == null) {
                scope.tooltipPlacement = "right";
            }

            transcludeFn(scope, function (clone) {
                var badge = element.find('.wbx-alert-icon');
                var tooltip = angular.element('<div class="wbx-validationMessageTemplate tooltip-danger" />');

                tooltip.append(clone);
                element.append(tooltip);

                $timeout(function () {
                    scope.$field = formController[attr.target];
                    badge.tooltip({
                        placement: scope.tooltipPlacement,
                        html: true,
                        title: clone,
                        container: 'body'
                    });

                });
            });
        }
    };
}]);

app.directive('wbxRequiredValidationTooltip', ['$timeout', function ($timeout) {
    return {
        restrict: 'E',
        transclude: true,
        require: '^form',
        scope: {
            tooltipPlacement: '=?'
        },

        template: '<div class="wbx-required-icon fa fa-caret-left fa-lg"></div>',
        link: function (scope, element, attr, formController, transcludeFn) {
            scope.$form = formController;
            if (scope.tooltipPlacement == null) {
                scope.tooltipPlacement = "right";
            }

            transcludeFn(scope, function (clone) {
                var badge = element.find('.wbx-required-icon');
                $timeout(function () {
                    scope.$field = formController[attr.target];
                    badge.tooltip({
                        placement: scope.tooltipPlacement,
                        html: true,
                        title: 'Required',
                        container: 'body'
                    });

                });
            });
        }

    };
}]);

app.directive('wbxValidateDate', function () {
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function (scope, element, attrs, ngModel) {
            var validate = function (viewValue) {
                var isValid = viewValue == null || viewValue == '' || moment(viewValue).isValid();
                ngModel.$setValidity('incomplete', isValid);
                return viewValue;
            };

            ngModel.$parsers.unshift(validate);
            ngModel.$formatters.push(validate);
        }
    }
});

app.directive('wbxIsNotFuture', [
    function () {
        var link = function ($scope, $element, $attrs, ngModel) {
            var validate = function (viewValue) {

                let isValid = !viewValue
                              || moment(viewValue).isValid() && !moment(viewValue).isAfter(moment(), 'days')
                              || dateIsIncomplete(viewValue);

                ngModel.$setValidity('isNotFuture', isValid);
                return viewValue;
            };

            ngModel.$parsers.unshift(validate);
            ngModel.$formatters.push(validate);
        };

        return {
            require: 'ngModel',
            link: link
        };

    }
]);

/**
* Accepts a string or momentJS date in the format dd/mm/yyyy
* @returns true if any portion of the date contains 'd' or 'm' or 'y'
* Example input/output:
* 01/01/yyyy -> true
* 01/01/2020 -> false
*/
let dateIsIncomplete = function(date) {
     return !date
         || date.indexOf('m') > -1
         || date.indexOf('d') > -1
         || date.indexOf('y') > -1;
};

app.directive('wbxIsBefore', [
    function () {
        var link = function ($scope, $element, $attrs, ngModel) {
            var validate = function (viewValue) {

                let isValid = viewValue
                            && $attrs.wbxIsBefore
                            && moment(viewValue).isValid()
                            && moment($attrs.wbxIsBefore).isValid()
                            && moment(viewValue).isBefore(moment($attrs.wbxIsBefore), 'days')
                            || dateIsIncomplete(viewValue)
                            || dateIsIncomplete($attrs.wbxIsBefore);

                ngModel.$setValidity('isBefore', isValid);
                return viewValue;
            };

            ngModel.$parsers.unshift(validate);
            ngModel.$formatters.push(validate);

            $attrs.$observe('wbxIsBefore', function (comparisonModel) {
                // Whenever the comparison model changes we'll re-validate
                return validate(ngModel.$viewValue);
            });
        };

        return {
            require: 'ngModel',
            link: link
        };

    }
]);

app.directive('wbxIsAfter', [
    function () {
        var link = function ($scope, $element, $attrs, ngModel) {

            var validate = function (viewValue) {
                let isValid = viewValue
                            && $attrs.wbxIsAfter
                            && moment(viewValue).isValid()
                            && moment($attrs.wbxIsAfter).isValid()
                            && !moment(viewValue).isBefore(moment($attrs.wbxIsAfter), 'days')
                            || dateIsIncomplete(viewValue)
                            || dateIsIncomplete($attrs.wbxIsAfter);

                ngModel.$setValidity('isAfter', isValid);
                return viewValue;
            };

            ngModel.$parsers.unshift(validate);
            ngModel.$formatters.push(validate);

            $attrs.$observe('wbxIsAfter', function (comparisonModel) {
                // Whenever the comparison model changes we'll re-validate
                return validate(ngModel.$viewValue);
            });
        };

        return {
            require: 'ngModel',
            link: link
        };

    }
]);

app.directive('wbxDateRange', [
    function () {
        var link = function ($scope, $element, $attrs, ngModel) {
            var validate = function (viewValue) {
                var isValid = true;
                if (viewValue != null && viewValue != '' &&
                    $attrs.wbxDateRange != null && $attrs.wbxDateRange != '') {
                    var viewValueMoment = moment(viewValue);
                    var dateRangeMoment = moment($attrs.wbxDateRange);
                    if (viewValueMoment.isValid() && dateRangeMoment.isValid()) {
                        var minDateMoment = moment.min(viewValueMoment, dateRangeMoment);
                        var calculatedFutureDateMoment;
                        if ($attrs.wbxMaxYears != null) {
                            calculatedFutureDateMoment = minDateMoment.add($attrs.wbxMaxYears, 'years');
                        }
                        else if ($attrs.wbxMaxMonths != null) {
                            calculatedFutureDateMoment = minDateMoment.add($attrs.wbxMaxMonths, 'months');
                        }
                        else if ($attrs.wbxMaxDays != null) {
                            calculatedFutureDateMoment = minDateMoment.add($attrs.wbxMaxDays, 'days');
                        }

                        var maxDateMoment = moment.max(viewValueMoment, dateRangeMoment);
                        isValid = maxDateMoment.isSameOrBefore(calculatedFutureDateMoment);
                    }
                }

                ngModel.$setValidity('wbxDateRange', isValid);
                return viewValue;
            };

            ngModel.$parsers.unshift(validate);
            ngModel.$formatters.push(validate);

            $attrs.$observe('wbxDateRange', function (comparisonModel) {
                // Whenever the comparison model changes we'll re-validate
                return validate(ngModel.$viewValue);
            });

        };

        return {
            require: 'ngModel',
            link: link
        };

    }
]);

app.directive('wbxMinAge', [
    function () {
        var link = function ($scope, $element, $attrs, ngModel) {
            var validate = function (viewValue) {
                var isValid = true;
                var pat = /^\-?[0-9]*$/;
                var isValidMinAge = pat.test($attrs.wbxMinAge);
                if (viewValue != null && viewValue != '' &&
                    $attrs.wbxMinAge != null && $attrs.wbxMinAge != '' &&
                    moment(viewValue).isValid() && isValidMinAge) {
                    var minAgeDate = moment().subtract($attrs.wbxMinAge, 'years');
                    if (moment(viewValue).isAfter(minAgeDate, 'days')) {
                        //If the date entered is after the calculated min age, that means it's too young.
                        isValid = false;
                    }
                }

                ngModel.$setValidity('minAge', isValid);
                return viewValue;
            };

            ngModel.$parsers.unshift(validate);
            ngModel.$formatters.push(validate);

            $attrs.$observe('wbxMinAge', function (comparisonModel) {
                // Whenever the comparison model changes we'll re-validate
                return validate(ngModel.$viewValue);
            });
        };

        return {
            require: 'ngModel',
            link: link
        };

    }
]);

app.directive('wbxValidateTime', function () {
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function (scope, element, attrs, ngModel) {
            var validate = function (viewValue) {
                var valid = true;
                if (viewValue) {
                    if (viewValue.charAt(4) == 'm' || viewValue.charAt(6) == 'x') {
                        //Not complete
                        valid = false;
                    }
                    else {
                        valid = true;
                    }
                }
                ngModel.$setValidity('incomplete', valid);
                return viewValue;
            };

            ngModel.$parsers.unshift(validate);
            ngModel.$formatters.push(validate);
        }
    }
});

app.directive('wbxIsAfterTime', [
    function () {
        var link = function ($scope, $element, $attrs, ngModel) {
            var validate = function (viewValue) {
                var isValid = true;

                if (viewValue != null && viewValue != '' &&
                    $attrs.wbxIsAfterTime != null && $attrs.wbxIsAfterTime != '') {
                    var curTimeMoment = moment(viewValue, moment.ISO_8601);
                    if (!curTimeMoment.isValid()) {
                        //This is is for either manual user enter or being set with just the time and am/pm format
                        if (viewValue.indexOf("am") > -1 || viewValue.indexOf("pm") > -1) {
                            curTimeMoment = moment(viewValue, "hh:mm:ss a");
                        }
                    }

                    var isAfterTimeMoment = moment($attrs.wbxIsAfterTime, moment.ISO_8601);
                    if (!isAfterTimeMoment.isValid()) {
                        //This is is for either manual user enter or being set with just the time and am/pm format
                        if ($attrs.wbxIsAfterTime.indexOf("am") > -1 || $attrs.wbxIsAfterTime.indexOf("pm") > -1) {
                            isAfterTimeMoment = moment($attrs.wbxIsAfterTime, "hh:mm:ss a");
                        }
                    }

                    if (curTimeMoment != null && curTimeMoment != '' &&
                        isAfterTimeMoment != null && isAfterTimeMoment != '' &&
                        curTimeMoment.isValid() && isAfterTimeMoment.isValid() &&
                        curTimeMoment.isBefore(isAfterTimeMoment, 'second')) {
                        isValid = false;
                    }
                }

                ngModel.$setValidity('isAfterTime', isValid);
                return viewValue;
            };

            ngModel.$parsers.unshift(validate);
            ngModel.$formatters.push(validate);

            $attrs.$observe('wbxIsAfterTime', function (comparisonModel) {
                // Whenever the comparison model changes we'll re-validate
                return validate(ngModel.$modelValue);
            });
        };

        return {
            require: 'ngModel',
            link: link
        };

    }
]);

app.directive('wbxIsBeforeTime', [
    function () {
        var link = function ($scope, $element, $attrs, ngModel) {
            var validate = function (viewValue) {
                var isValid = true;

                if (viewValue != null && viewValue != '' &&
                    $attrs.wbxIsBeforeTime != null && $attrs.wbxIsBeforeTime != '') {

                    var curTimeMoment = moment(viewValue, moment.ISO_8601);
                    if (!curTimeMoment.isValid()) {
                        //This is is for either manual user enter or being set with just the time and am/pm format
                        if (viewValue.indexOf("am") > -1 || viewValue.indexOf("pm") > -1) {
                            curTimeMoment = moment(viewValue, "hh:mm:ss a");
                        }
                    }

                    var isBeforeTimeMoment = moment($attrs.wbxIsBeforeTime, moment.ISO_8601);
                    if (!isBeforeTimeMoment.isValid()) {
                        //This is is for either manual user enter or being set with just the time and am/pm format
                        if ($attrs.wbxIsBeforeTime.indexOf("am") > -1 || $attrs.wbxIsBeforeTime.indexOf("pm") > -1) {
                            isBeforeTimeMoment = moment($attrs.wbxIsBeforeTime, "hh:mm:ss a");
                        }
                    }

                    if (curTimeMoment != null && curTimeMoment != '' &&
                        isBeforeTimeMoment != null && isBeforeTimeMoment != '' &&
                        curTimeMoment.isValid() && isBeforeTimeMoment.isValid() &&
                        curTimeMoment.isAfter(isBeforeTimeMoment, 'second')) {
                        isValid = false;
                    }
                }

                ngModel.$setValidity('isBeforeTime', isValid);
                return viewValue;
            };

            ngModel.$parsers.unshift(validate);
            ngModel.$formatters.push(validate);

            $attrs.$observe('wbxIsBeforeTime', function (comparisonModel) {
                // Whenever the comparison model changes we'll re-validate
                return validate(ngModel.$modelValue);
            });
        };

        return {
            require: 'ngModel',
            link: link
        };

    }
]);

app.directive('wbxHasValue', [
    function () {
        var link = function ($scope, $element, $attrs, ngModel) {
            var validate = function (viewValue) {
                var otherValue = $attrs.wbxHasValue;
                var thisValue = viewValue;
                var valid = thisValue == null || thisValue == "" || (thisValue != null && thisValue != "" && otherValue != null && otherValue != "");

                ngModel.$setValidity('noValue', valid);
                return viewValue;
            };

            ngModel.$parsers.unshift(validate);
            ngModel.$formatters.push(validate);

            $attrs.$observe('wbxHasValue', function (comparisonModel) {
                // Whenever the comparison model changes we'll re-validate
                return validate(ngModel.$viewValue);
            });

        };

        return {
            require: 'ngModel',
            link: link
        };

    }
]);

app.directive('wbxValidateMinCharacters', function () {
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function (scope, element, attrs, ngModel) {
            var validate = function (viewValue) {
                var minCharacters = attrs.wbxValidateMinCharacters;
                var valid = true;
                if (viewValue != null && viewValue.trim() != "") {
                    if ((viewValue.replace(/([-~!@#$%^&*()_+=`{}\[\]\|\\:;'<>,.\/? ])+/g, '')).length < minCharacters) {
                        //Not complete
                        valid = false;
                    }
                    else {
                        valid = true;
                    }
                }
                ngModel.$setValidity('incomplete', valid);
                return viewValue;
            };

            ngModel.$parsers.unshift(validate);
            ngModel.$formatters.push(validate);
        }
    }
});

app.directive('wbxValidateMinCharactersVariableLength', function () {
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function (scope, element, attrs, ngModel) {
            var validate = function (viewValue) {
                var minCharacters = attrs.wbxValidateMinCharactersVariableLength;
                var valid = true;
                if (viewValue != null && viewValue.trim() != "") {
                    if ((viewValue.replace(/([-~!@#$%^&*()_+=`{}\[\]\|\\:;'<>,.\/? ])+/g, '')).length < minCharacters) {
                        //Not complete
                        valid = false;
                    }
                    else {
                        valid = true;
                    }
                }
                ngModel.$setValidity('minCharactersVariableLength', valid);
                return viewValue;
            };

            ngModel.$parsers.unshift(validate);
            ngModel.$formatters.push(validate);
        }
    }
});

app.directive('wbxValidateNpi', function () {
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function (scope, element, attrs, ngModel) {
            var validate = function (viewValue) {
                var valid = true;
                if (viewValue != null && viewValue.trim() != "") {
                    if (viewValue.length == 0)
                        valid = true;
                    else if (viewValue.length != 10)
                        valid = false;
                    else {
                        var checkDigit = 0;
                        for (var i = 0; i < viewValue.length - 1; i++) {
                            if (i % 2 == 0) {
                                var r = viewValue.substring(i, i + 1) * 2;
                                if (r >= 10) {
                                    //For multiple digits, add individual digit
                                    checkDigit += (("" + r).substring(0, 1) * 1) + (("" + r).substring(1, 2) * 1);
                                }
                                else {
                                    checkDigit += r;
                                }
                            }
                            else {
                                checkDigit += viewValue.substring(i, i + 1) * 1;
                            }
                        }
                        // For prefix 80840 which is not included on the NPI
                        checkDigit += 24;

                        if (checkDigit % 10 == 0) {
                            //If the last digit is 0, the checkDigit will be 0
                            checkDigit = 0;
                        }
                        else {
                            //If the last digit isn't 0, minus the value from the next rounded 10
                            checkDigit = ((parseInt(checkDigit / 10) + 1) * 10) - checkDigit;
                        }

                        valid = (viewValue.substring(9, 10) == checkDigit);
                    }
                }
                else {
                    valid = true;
                }
                ngModel.$setValidity('npi', valid);
                return viewValue;
            };

            ngModel.$parsers.unshift(validate);
            ngModel.$formatters.push(validate);
        }
    }
});

app.directive('wbxValidateEmail', function () {
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function (scope, element, attrs, ngModel) {
            
            const regEx = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; 
            ngModel.$validators.email = function (modelValue, viewValue) {
                if (ngModel.$isEmpty(modelValue)) return true;
                return  regEx.test(viewValue);
            };
                   
        }
    }
});

app.directive('wbxValidateUrl', function () {
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function (scope, element, attrs, ngModel) {
            var validate = function (viewValue) {
                var valid = true;
                if (viewValue) {
                    var regEx = /^(http(s)?)?(\:\/\/)?[\w-]+(\.[\w-]+)+([\w.,@?^!=%&amp;:\/~+#-]*[\w@?^=%&amp;\/~+#-])+$/gmi; 
                    valid = regEx.test(viewValue);
                }
                ngModel.$setValidity('url', valid);
                return viewValue;
            };

            ngModel.$parsers.unshift(validate);
            ngModel.$formatters.push(validate);
        }
    }
});

app.directive('wbxIsMatched', [
    function () {
        var link = function ($scope, $element, $attrs, ngModel) {
            var validate = function (viewValue) {
                //If this isn't specified, assume it's case sensitive
                var isCaseSensitive = $attrs.wbxCaseSensitive != null ? $attrs.wbxCaseSensitive : 'true';
                var otherValue = $attrs.wbxIsMatched != null ? $attrs.wbxIsMatched : "";
                var thisValue = viewValue != null ? viewValue : "";
                var valid = false;
                if (isCaseSensitive == 'true') {
                    valid = otherValue == thisValue;
                }
                else {
                    valid = otherValue.toLowerCase() == thisValue.toLowerCase();
                }

                ngModel.$setValidity('notMatched', valid);
                return viewValue;
            };

            ngModel.$parsers.unshift(validate);
            ngModel.$formatters.push(validate);

            $attrs.$observe('wbxIsMatched', function (comparisonModel) {
                // Whenever the comparison model changes we'll re-validate
                return validate(ngModel.$viewValue);
            });

        };

        return {
            require: 'ngModel',
            link: link
        };

    }
]);

app.directive('wbxIsBeforeInt', [
    function () {
        var link = function ($scope, $element, $attrs, ngModel) {
            var validate = function (viewValue) {
                var valid = true;  // Assume valid if either model does not contain a valid int.
                var pat = /^\-?[0-9]*$/;
                var bValidInt = pat.test(viewValue);
                if (bValidInt) {
                    var comparisonModel = $attrs.wbxIsBeforeInt;
                    if (comparisonModel && pat.test(comparisonModel)) {

                        var fromInt = parseInt(comparisonModel);
                        var toInt = parseInt(viewValue);

                        valid = fromInt >= toInt;
                    }
                }

                ngModel.$setValidity('isBeforeInt', valid);
                return viewValue;
            };

            ngModel.$parsers.unshift(validate);
            ngModel.$formatters.push(validate);

            $attrs.$observe('wbxIsBeforeInt', function (comparisonModel) {
                // Whenever the comparison model changes we'll re-validate
                return validate(ngModel.$viewValue);
            });

        };

        return {
            require: 'ngModel',
            link: link
        };

    }
]);

app.directive('wbxIsAfterInt', [
    function () {
        var link = function ($scope, $element, $attrs, ngModel) {
            var validate = function (viewValue) {
                var valid = true;  // Assume valid if either model does not contain a valid int.
                var pat = /^\-?[0-9]*$/;
                var bValidInt = pat.test(viewValue);
                if (bValidInt) {
                    var comparisonModel = $attrs.wbxIsAfterInt;
                    if (comparisonModel && pat.test(comparisonModel)) {

                        var fromInt = parseInt(comparisonModel);
                        var toInt = parseInt(viewValue);

                        valid = fromInt <= toInt;

                    }
                }

                ngModel.$setValidity('isAfterInt', valid);
                return viewValue;
            };

            ngModel.$parsers.unshift(validate);
            ngModel.$formatters.push(validate);

            $attrs.$observe('wbxIsAfterInt', function (comparisonModel) {
                // Whenever the comparison model changes we'll re-validate
                return validate(ngModel.$viewValue);
            });

        };

        return {
            require: 'ngModel',
            link: link
        };

    }
]);

//http://www.brainjar.com/js/validation/
app.directive('wbxValidateRoutingNumber', function () {
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function (scope, element, attrs, ngModel) {

            var validate = function (viewValue) {
                var valid = true;
                if (viewValue != null && viewValue.trim() != "") {

                    //Check if value is redacted
                    if (viewValue.indexOf("*****") !== -1 && viewValue.length === 9) {
                        ngModel.$setValidity('routingNumber', true);
                        return viewValue;
                    }

                    var i, n, t;

                    // First, remove any non-numeric characters.

                    t = "";
                    for (i = 0; i < viewValue.length; i++) {
                        c = parseInt(viewValue.charAt(i), 10);
                        if (c >= 0 && c <= 9)
                            t = t + c;
                    }

                    // Check the length, it should be nine digits.

                    if (viewValue.length < 9) {
                        //valid = false;
                        ngModel.$setValidity('incomplete', false);
                        return viewValue;
                    } else {
                        ngModel.$setValidity('incomplete', true);

                    }
                       

                    // Now run through each digit and calculate the total.

                    n = 0;
                    for (i = 0; i < t.length; i += 3) {
                        n += parseInt(t.charAt(i), 10) * 3
                            + parseInt(t.charAt(i + 1), 10) * 7
                            + parseInt(t.charAt(i + 2), 10);
                    }

                    // If the resulting sum is an even multiple of ten (but not zero),
                    // the aba routing number is good.

                    if ( n != 0 && n % 10 == 0)
                        valid = true;
                    else
                        valid = false;

                }

                ngModel.$setValidity('routingNumber', valid);
                return viewValue;
            };

            ngModel.$parsers.unshift(validate);
            ngModel.$formatters.push(validate);
        }
    }
});


app.directive('wbxValidateAccountNumber', function () {
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function (scope, element, attrs, ngModel) {

            var validate = function (viewValue) {
                var valid = true;
                if (viewValue != null && viewValue.trim() !== "") {

                    if (viewValue.length < 4 || viewValue.length > 17) {
                        valid = false;
                    }
                }
                ngModel.$setValidity('ADA_AccountNumber', valid);
                return viewValue;
            };

            ngModel.$parsers.unshift(validate);
            ngModel.$formatters.push(validate);
        }
    }
});

//This is to validate value to be >= minimum value.
app.directive('wbxValidateMinValue', function () {
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function (scope, element, attrs, ngModel) {

            var validate = function (viewValue) {
                var valid = true;
                if(viewValue != ""){           
                    var pat = /^\-?[0-9]*\.?[0-9]*$/;
                    var bValidInt = pat.test(viewValue);
                    if (bValidInt) {
                        var comparisonValue = attrs.wbxValidateMinValue;
                        if (comparisonValue && pat.test(comparisonValue)) {
                            var minLimit = parseFloat(comparisonValue);
                            var valueInt = parseFloat(viewValue);
                            valid = minLimit <= valueInt;
                        }
                    }
                }

                ngModel.$setValidity('minValue', valid);
                return viewValue;
            };

            ngModel.$parsers.unshift(validate);
            ngModel.$formatters.push(validate);

            attrs.$observe('wbxValidateMinValue', function (comparisonValue) {
                // Whenever the comparison model changes we'll re-validate
                return validate(ngModel.$viewValue);
            });
        }
    }
});

//This is to validate value to be <= max value.
app.directive('wbxValidateMaxValue', function () {
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function (scope, element, attrs, ngModel) {

            var validate = function (viewValue) {
                var valid = true;
                if(viewValue != ""){  
                    var pat = /^\-?[0-9]*\.?[0-9]*$/;
                    var bValidInt = pat.test(viewValue);
                    if (bValidInt) {
                        var comparisonValue = attrs.wbxValidateMaxValue;
                        if (comparisonValue && pat.test(comparisonValue)) {
                            var maxLimit = parseFloat(comparisonValue);
                            var valueInt = parseFloat(viewValue);

                            valid = maxLimit >= valueInt;
                        }
                    }
                }

                ngModel.$setValidity('maxValue', valid);
                return viewValue;
            };

            ngModel.$parsers.unshift(validate);
            ngModel.$formatters.push(validate);

            attrs.$observe('wbxValidateMaxValue', function (comparisonValue) {
                // Whenever the comparison model changes we'll re-validate
                return validate(ngModel.$viewValue);
            });
        }
    }
});

/**
 * Above this line, ES and Portals are exactly the same. If any is changed, make sure it's sync'd up
 */



/**
 * Only used in Portals (reassess if ES needs it as well)
 */

// for MM/YYYY date entry
app.directive('wbxIsNotFutureMonthYear', [
    function () {
        var link = function ($scope, $element, $attrs, ngModel) {
            var validate = function (viewValue) {

                // For expressions which determine if directive should even be run.
                // If directive shouldn't be run then set validity to true
                if ($attrs.wbxIsNotFutureMonthYear.length > 0 && !$scope.$eval($attrs.wbxIsNotFutureMonthYear)) {
                    ngModel.$setValidity('isNotFutureMonthYear', true);
                }

                var valid = true;  // Assume valid if either model does not contain a valid date.
                var pat = /[my]/i;
                var bInvalidDate = pat.test(viewValue);
                if (!bInvalidDate) {

                    var today = new Date(Date());
                    if (viewValue) {
                        var f = new Date(viewValue.substr(0, 2) + '-01-' + viewValue.substr(3, 4));
                        if (!isNaN(f.getTime())) {
                            // Valid if model is less than or equal to the model we're comparing against.
                            valid = today.getTime() > f.getTime();
                        }
                    }
                }
                ngModel.$setValidity('isNotFutureMonthYear', valid);
                return viewValue;
            };

            var conditionChange = function (viewValue) {
                ngModel.$setValidity('isNotFutureMonthYear', true);

                if (viewValue == true)
                    return validate(ngModel.$modelValue);
            };

            ngModel.$parsers.unshift(validate);
            ngModel.$formatters.push(validate);
            $scope.$watch($attrs.wbxIsNotFutureMonthYear, conditionChange);
        };

        return {
            require: 'ngModel',
            link: link
        };

    }
]);

app.directive('wbxIsAfterMmyyyy', [
    function () {
        var link = function ($scope, $element, $attrs, ngModel) {
            var validate = function (viewValue) {
                var valid = true;  // Assume valid if either model does not contain a valid date.
                var pat = /((0[1-9])|(1[0-2]))\/(\d{4})/;
                var bValidDate = pat.test(viewValue);
                if (bValidDate) {
                    var comparisonModel = $attrs.wbxIsAfterMmyyyy;
                    if (comparisonModel && pat.test(comparisonModel)) {

                        var fromDate = comparisonModel.substr(3, 4) + comparisonModel.substr(0, 2);
                        var toDate = viewValue.substr(3, 4) + viewValue.substr(0, 2);

                        valid = fromDate <= toDate;

                    }
                }

                ngModel.$setValidity('isAfter', valid);
                return viewValue;
            };

            ngModel.$parsers.unshift(validate);
            ngModel.$formatters.push(validate);

            $attrs.$observe('wbxIsAfterMmyyyy', function (comparisonModel) {
                // Whenever the comparison model changes we'll re-validate
                return validate(ngModel.$viewValue);
            });

        };

        return {
            require: 'ngModel',
            link: link
        };

    }
]);

app.directive('wbxDoesNotMatch', [
    function () {
        var link = function ($scope, $element, $attrs, ngModel) {
            var validate = function (viewValue) {
                var otherValue = $attrs.wbxDoesNotMatch != null ? $attrs.wbxDoesNotMatch : "";
                var thisValue = viewValue != null ? viewValue : "";
                var valid = otherValue != thisValue;

                ngModel.$setValidity('Matches', valid);
                return viewValue;
            };

            ngModel.$parsers.unshift(validate);
            ngModel.$formatters.push(validate);

            $attrs.$observe('wbxDoesNotMatch', function (comparisonModel) {
                // Whenever the comparison model changes we'll re-validate
                return validate(ngModel.$viewValue);
            });

        };

        return {
            require: 'ngModel',
            link: link
        };

    }
]);

app.directive('wbxValidatePasswordPolicy', function () {
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function (scope, element, attrs, ngModel) {
            var validate = function (viewValue) {
                var isPasswordValid = attrs.wbxValidatePasswordPolicy;
                var valid = (isPasswordValid == 'true');
                ngModel.$setValidity('PasswordNotValid', valid);
                return viewValue;
            };

            ngModel.$parsers.unshift(validate);
            ngModel.$formatters.push(validate);

            attrs.$observe('wbxValidatePasswordPolicy',
                function (comparisonModel) {
                    // Whenever the comparison model changes we'll re-validate
                    return validate(ngModel.$viewValue);
                });
        }
    }
});

/**
 * Will be deprecated
 */

app.directive('wbxValidatePhone', function () {
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function (scope, element, attrs, ngModel) {
            var validate = function (viewValue) {
                var valid = true;
                if (viewValue) {
                    if ((viewValue.replace(/([-~!@#$%^&*()_+=`{}\[\]\|\\:;'<>,.\/? ])+/g, '')).length !== 10) {
                        //Not complete
                        valid = false;
                    }
                    else {
                        valid = true;
                    }
                }
                ngModel.$setValidity('incomplete', valid);
                return viewValue;
            };

            ngModel.$parsers.unshift(validate);
            ngModel.$formatters.push(validate);
        }
    }
});

app.directive('wbxValidateZip', function () {
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function (scope, element, attrs, ngModel) {
            var validate = function (viewValue) {
                var valid = true;
                if (viewValue) {
                    if ((viewValue.replace(/([-~!@#$%^&*()_+=`{}\[\]\|\\:;'<>,.\/? ])+/g, '')).length !== 5) {
                        //Not complete
                        valid = false;
                    }
                    else {
                        valid = true;
                    }
                }
                ngModel.$setValidity('incompleteZip', valid);
                return viewValue;
            };

            ngModel.$parsers.unshift(validate);
            ngModel.$formatters.push(validate);
        }
    }
});

app.directive('wbxValidateExpDate', function () {
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function (scope, element, attrs, ngModel) {
            var validate = function (viewValue) {
                var isValid = viewValue && viewValue.length == 5;

                if (isValid) {
                    var viewValueParts = viewValue.split('/');
                    var viewValueInterpreted = viewValueParts[0] + '/20' + viewValueParts[1]
                    var viewValueMoment = moment(viewValueInterpreted, 'MM/YYYY');

                    isValid = isValid && viewValueMoment.isValid();
                }

                ngModel.$setValidity('incomplete', isValid);

                var isFutureExpDate = isValid ? viewValueMoment.isAfter(moment().subtract(1, 'months'), 'months') : true;
                ngModel.$setValidity('isFutureExpDate', isFutureExpDate);

                return viewValue;
            };

            ngModel.$parsers.unshift(validate);
            ngModel.$formatters.push(validate);
        }
    }
});

app.directive('wbxValidateCvc', function () {
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function (scope, element, attrs, ngModel) {
            var validate = function (viewValue) {
                let isValid = !!viewValue && viewValue.length >= 3;
                ngModel.$setValidity('incomplete', isValid);
                return viewValue;
            };

            ngModel.$parsers.unshift(validate);
            ngModel.$formatters.push(validate);
        }
    }
});

app.directive('wbxValidateConfirmRoutingNumber', function () {
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function (scope, element, attrs, ngModel) {
            var validate = function (viewValue) {
                ngModel.$setValidity('routingNumbersMatch', viewValue == attrs.wbxRoutingNumberValue);
                return viewValue;
            };

            ngModel.$parsers.unshift(validate);
            ngModel.$formatters.push(validate);

            attrs.$observe('wbxRoutingNumberValue', function () {
                return validate(ngModel.$viewValue);
            });
        }
    }
});

app.directive('wbxValidateConfirmAccountNumber', function () {
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function (scope, element, attrs, ngModel) {
            var validate = function (viewValue) {
                ngModel.$setValidity('accountNumbersMatch', viewValue == attrs.wbxAccountNumberValue);
                return viewValue;
            };

            ngModel.$parsers.unshift(validate);
            ngModel.$formatters.push(validate);

            attrs.$observe('wbxAccountNumberValue', function () {
                return validate(ngModel.$viewValue);
            });
        }
    }
});

app.directive('wbxValidateRoutingNumberLenght', function () {
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function (scope, element, attrs, ngModel) {
            var validate = function (viewValue) {
                let isValid = !!viewValue && viewValue.length === 9;
                ngModel.$setValidity('routingNumberLength', isValid);
                return viewValue;
            };

            ngModel.$parsers.unshift(validate);
            ngModel.$formatters.push(validate);
        }
    }
});;
//These directives are mainly used by wrappers and need to exist and sync'd up in both ES and Portals solutions

//This is to auto dismiss success banner after 5 seconds
app.directive('wbxAutoDismiss', [function () {
    return {
        restrict: 'A',
        scope: {
            wbxAutoDismiss: '=',
            wbxAutoTopScroll: '<'
        },
        controller: ['$scope', '$timeout', function ($scope, $timeout) {
            $scope.$watch('wbxAutoDismiss', function (n, o) {
                //Only scroll up if it's shown and it wasn't already shown
                if (n != null && n) {
                    document.getElementById($scope.BannerId).hidden = false;
                    var origOffsetY = document.getElementById('header') != null ? document.getElementById('header').offsetHeight : 50;  //Header height
                    var mainNavHt = document.getElementById('mainNav') != null ? document.getElementById('mainNav').offsetHeight - 40 : 0; //Navbar height
                    var headerOffset = origOffsetY + mainNavHt;

                    if ($('#' + $scope.BannerId).offset() == undefined) {
                        console.log("WbxUtils is being used.");
                    }
                    else {
                        $timeout(function () {
                            $('html, body').animate({
                                scrollTop: $scope.wbxAutoTopScroll === true? 0 : $('#' + $scope.BannerId).offset().top - headerOffset - 30
                            }, "fast");
                        }, 100);
                        $timeout(function () {
                            $scope.wbxAutoDismiss = false;
                            document.getElementById($scope.BannerId).hidden = true;
                        }, 5000);
                    }
                }
            });
        }],
        link: function (scope, element, attr) {
            scope.BannerId = attr.id;
        }
    };
}]);

app.directive('wbxAutoScroll', [function () {
    return {
        restrict: 'A',
        scope: {
            wbxAutoScroll: '=',
            wbxAutoTopScroll: '<'
        },
        controller: ['$scope', '$timeout', function ($scope, $timeout) {
            $scope.$watch('wbxAutoScroll', function (n, o) {
                //Only scroll up if it's shown and it wasn't already shown
                if (n != null && n != o && n) {
                    if (!$scope.IsInsideModal) {
                        var origOffsetY = document.getElementById('header') != null ? document.getElementById('header').offsetHeight : 0;  //Header height
                        var mainNavHt = document.getElementById('mainNav') != null ? document.getElementById('mainNav').offsetHeight - 40 : 0; //Navbar height
                        var headerOffset = origOffsetY + mainNavHt;
                        var wbxStepperOffset = document.getElementById('Wbx-Stepper') != null ? document.getElementById('mainNav').offsetHeight + headerOffset + 170 : 0;

                        if ($('#' + $scope.BannerId).offset() == undefined) {
                            console.log("WbxUtils is being used.");
                        }
                        else {
                            $timeout(function () {
                                $('html, body').animate({
                                    scrollTop: $scope.wbxAutoTopScroll === true? 0 : $('#' + $scope.BannerId).offset().top - headerOffset - 30
                                }, "fast");
                            }, 100);
                        }
                    }
                    else {
                        //If the banner is inside a modal
                        if ($('#' + $scope.BannerId).offset() == undefined) {
                            console.log("WbxUtils is being used.");
                        }
                        else {
                            $timeout(function () {
                                $scope.modalAlertParentElement.animate({
                                    scrollTop: 0
                                }, "fast");
                            }, 100);
                        }
                    }

                }
            });
        }],
        link: function (scope, element, attr) {
            scope.BannerId = attr.id;
            scope.element = element;

            scope.IsInsideModal = element.closest('div.modal').length > 0;
            if (scope.IsInsideModal) {
                scope.modalAlertParentElement = element.closest('div.wbx-modal-scrollable');

                //TODO: Needs to revisit on what to do if there's no wbx-modal-scrollable and the scrolling is needed
                //if (scope.modalAlertParentElement.length == 0) {
                //    //scope.modalAlertParentElement = element.closest('div.wbx-modal-body');
                //    //if (scope.modalAlertParentElement.length == 0) {
                //    //    scope.modalAlertParentElement = element.closest('div.modal-body');
                //    //}
                //}
            }
        }
    };
}]);

//This is mainly used to make tooltip dynamicaly shown.
//Can also be used to remove any other attribute
app.directive('wbxClearAttribute', [function () {
    return {
        restrict: 'A',
        scope: {
            show: '='
        },
        controller: ['$scope', '$attrs', function ($scope, $attrs) {
            $scope.attribute = $attrs.wbxClearAttribute;
            $scope.value = $attrs[$scope.attribute];
            $scope.$watch('show', function (n, o) {
                if (n) {
                    $attrs.$set($scope.attribute, $scope.value);
                } else {
                    $attrs.$set($scope.attribute, "");
                }
            });
        }]
    };
}]);

//This is used in merging the ngModels for checkboxes
app.directive('wbxMergeNgModel', [function () {
    return {
        restrict: 'A',
        require: 'ngModel',
        scope: {
            wbxMergeNgModel: '=?',
            wbxList: '=?'
        },
        controller: ['$scope', function ($scope) {
            $scope.$watch('wbxMergeNgModel', function (n, o) {
                if (n) {
                    $scope.NgModel.$setViewValue(true);
                } else {
                    $scope.NgModel.$setViewValue(false);
                }

                $scope.NgModel.$render();
            });

            $scope.$watch('wbxList', function (n, o) {
                if (n != null) {
                    var atLeastOneSelected = false;
                    angular.forEach($scope.wbxList, function (item) {
                        if (item.Selected) {
                            atLeastOneSelected = true;
                        }
                    });

                    if (atLeastOneSelected) {
                        $scope.NgModel.$setViewValue(true);
                    } else {
                        $scope.NgModel.$setViewValue(false);
                    }

                    $scope.NgModel.$render();
                }
            }, true);
        }],
        link: function (scope, element, attributes, ngModel) {
            scope.NgModel = ngModel;
        }
    };
}]);

app.directive('wbxRadioEnforcer', [function () {
    return {
        restrict: 'A',
        scope: {
            ngModel: '=',
            ngModelRadio: '=?',
            ngModelRadioList: '=?',
            ngModelProperty: '@'
        },
        controller: ['$scope', function ($scope) {
            $scope.$watchCollection('ngModel', function (n, o) {
                if (n != null && n != o && n) {
                    if ($scope.ngModelRadio != null) {
                        //This is when the radio button is set manually.
                        //The ngModelRadio format would be { Yes: true, No: null }
                        //The ngModelProperty would be Yes and No
                        angular.forEach($scope.ngModelRadio, function (value, key) {
                            //Since this is to set the ngModel of other properties to null, 
                            // we need to exclude the SubSection data from being set to null
                            if (key != $scope.ngModelProperty && key.indexOf("SubSection") < 0) {
                                $scope.ngModelRadio[key] = null;
                            }
                        });
                    }
                    else if ($scope.ngModelRadioList != null) {
                        var index = 0;
                        //This is when the RadioButtonList is used (values coming from the database)
                        //The ngModelRadioList would be [{Selected: true}, {Selected: false}]
                        //The ngModelProperty would be the index.
                        angular.forEach($scope.ngModelRadioList, function (radioObject) {
                            if (index != $scope.ngModelProperty) {
                                radioObject.Selected = null;
                            }
                            index++;
                        });
                    }
                }
            });
        }]
    };
}]);

app.directive('wbxAutoSelect', [function () {
    return {
        restrict: 'A',
        scope: {
            ngModel: '=',
            list: '='
        },
        controller: ['$scope', function ($scope) {
            $scope.$watchCollection('list', function (n, o) {
                if (n != null && n.length == 1) {
                    $scope.ngModel = n[0].Value;
                }
            });
        }]
    };
}]);

//This will select all the values of the input box. If the input value is deleted, it will be saved in the directive isolated scope. 
//@Todo: Refactor - wbxSelectOnClick
app.directive('wbxRedactedInput', ['$window', function ($window) {
    return {
        restrict: 'A',
        scope: {
            ngModel: '='
        },
        require: ['ngModel', '^form'],
        link: function (scope, element, attrs, ctrl) {

            var ngModelCtrl = ctrl[0];
            var formCtrl = ctrl[1];
            var formName = element.closest("form")[0].id;

            element.on('click', function (event) {

                event.stopPropagation();
                if (scope.oldValue === "" || scope.oldValue === null || scope.oldValue === undefined) {
                    scope.oldValue = ngModelCtrl.$viewValue;
                };

                scope.selectAllInputContents(this);
            });

            element.on('blur', function (event) {
                event.stopPropagation();

                if (ngModelCtrl.$modelValue === undefined || ngModelCtrl.$modelValue === null) {

                    if (scope.oldValue === null || scope.oldValue === undefined) {
                        scope.oldValue = '';
                    }
                    else if (scope.oldValue.indexOf("**") !== -1) {
                        scope.ngModel = scope.oldValue;
                    }

                } else {

                    if (ngModelCtrl.$modelValue !== undefined && ngModelCtrl.$modelValue !== scope.oldValue) {
                        scope.oldValue = ngModelCtrl.$modelValue;
                    }
                }
                scope.updateViewValue(scope.oldValue);
                scope.$apply();
            });

            element.on('keydown', function () {
                event.stopPropagation();

                if (ngModelCtrl.$modelValue) {

                    if (ngModelCtrl.$modelValue.indexOf("*") !== -1) {

                        scope.selectAllInputContents(this);
                    }
                }
            });


            $("#" + formName).on('submit', function () {
                if (formCtrl.$submitted && formCtrl.$valid) {
                    scope.redactValue();
                }
            });

            scope.selectAllInputContents = function (vm) {
                if (!$window.getSelection().toString()) {
                    vm.setSelectionRange(0, vm.value.length);
                }
            }

            scope.redactValue = function () {
                var modelValue = ngModelCtrl.$modelValue ? ngModelCtrl.$modelValue.trim() : '';
                var redactdValue = "";

                if (modelValue.length - 4 <= 4) {
                    redactdValue = '*'.repeat(modelValue.length);
                } else {
                    var lastFour = modelValue.substr(modelValue.length - 4);
                    redactdValue = '*'.repeat(modelValue.length - 4) + lastFour;
                }
                scope.ngModel = redactdValue;
                scope.oldValue = redactdValue;

                scope.updateViewValue(redactdValue);

            }

            scope.updateViewValue = function (newValue) {
                ngModelCtrl.$modelValue = newValue;
                ngModelCtrl.$viewValue = newValue;
                ngModelCtrl.$render();

            }

        }
    };
}]);

app.directive('wbxStopPropagation', function () {
    return {
        restrict: 'A',
        link: function (scope, element) {
            element.bind('click', function (e) {
                return false;
            });
        }
    };
});;
app.filter('wbxContactsSign', function () {
    return function (a) {
        if (a == null) {
            return a;
        }

        if (a != "" && a >= 0) {
            a = "+" + a.toString();
        } else {
            a = a.toString();
        }
        return a;
    }
});;
(function () {
    'use strict';
    app.filter('wbxDatePresentFilter', wbxDatePresentFilter);

    wbxDatePresentFilter.$inject = [];

    function wbxDatePresentFilter() {
        return function (value) {
            if (value == null || value == '') {
                return "Present";
            }
            else {
                return value;
            }
        }
    }
})();;
app.filter('wbxDateFilter', function () {
    return function (value, mask) {
        if (value != undefined) {
           var dateString = value.toString();
            if (dateString.length > 0) {
                var d = new Date(dateString);
                if (mask) {
                    return "**/**/" + d.getFullYear().toString();
                }
                else {
                    return (d.getMonth() + 1).toString() + "/" + d.getDate().toString() + "/" + d.getFullYear().toString();
                }
            }
        }
        return "";
    }
});;
app.filter('wbxDeaFilter', function () {
    return function (value, mask) {
        if (value != undefined) {
            var val = value;
            var len = val.length;

            if (len <= 4)
                return val;

            if (mask)
                return "*****" + val.substr(len - 4, 4);
            else
                return val;
        }
    }
});;
(function () {
    'use strict';
    app.filter('wbxDropDownFilter', wbxDropDownFilter);

    wbxDropDownFilter.$inject = [];

    function wbxDropDownFilter() {
        return function (value, dropDownList) {
            if (value == null || dropDownList == null) {
                return null;
            }

            var keepGoing = true;
            value = value.trim().replace(/([-~!@#$%^&*()_+=`{}\[\]\|\\:;'<>,.\/? ])+/g, '');
            var result = null;
            angular.forEach(dropDownList, function (item) {
                if (keepGoing && item.Value == value) {
                    keepGoing = false;
                    result = item.Text;
                }
            });

            return result;
        }
    }

})();;
(function () {
    'use strict';
    app.filter('wbxEINFilter', wbxEinFilter);

    wbxEinFilter.$inject = [];

    function wbxEinFilter() {
        return function (value) {
            if (value == null) {
                return value;
            }
            var result = value.trim().replace(/([-~!@#$%^&*()_+=`{}\[\]\|\\:;'<>,.\/? ])+/g, '');
            result = result.substring(0, 2) + "-" + result.substring(3, result.length);

            return result;
        }
    }

})();;
(function () {
    'use strict';
    app.filter('wbxMultiSelectFilter', wbxMultiSelectFilter);

    wbxMultiSelectFilter.$inject = [];

    function wbxMultiSelectFilter() {
        return function join(array, separator, prop) {
            if (!Array.isArray(array)) {
                console.error("Error on filtering multi select. It's not an array.");
                return array; // if not array return original - can also throw error
            }

            var result = (!angular.isUndefined(prop) ? array.map(function (item) {
                return item[prop];
            }) : array).join(separator);

            return result;
        };
    }
})();;
(function () {
    'use strict';
    app.filter('wbxPercentageFilter', wbxPercentageFilter);

    wbxPercentageFilter.$inject = [];

    function wbxPercentageFilter() {
        return function (value) {
            if (value == null || value == '') {
                return value;
            }
            else {
                return value + ' %';
            }
        }
    }
})();;
(function () {
    'use strict';
    app.filter('wbxPhoneFilter', wbxPhoneFilter);

    wbxPhoneFilter.$inject = [];

    function wbxPhoneFilter() {
        return function (value) {
            if (value == null) {
                return value;
            }

            var result = value.trim().replace(/([-~!@#$%^&*()_+=`{}\[\]\|\\:;'<>,.\/? ])+/g, '');

            //After replacing the parenthesis and dashes, if it's empty string or null, just return null
            if (result == '' || result == null) {
                return null;
            }

            result = "(" + result.substring(0, 3) + ") " + result.substring(3, 6) + "-" + result.substring(6, result.length);

            return result;
        }
    }

})();;
app.filter('wbxRxNumberUnsigned', function () {
    return function (a, b) {
        if (a == null) {
            return "--";
        } else {
            a = a.toFixed(b);
            a = a.toString();

            return a;
        }
    }
});;
app.filter('wbxRxNumber', function () {
    return function (a, b) {
        if (a == null) {
            return "--";
        } else {
            a = a.toFixed(b);

            if (a >= 0) {
                a = "+" + a.toString();
            } else {
                a = a.toString();
            }

            return a;
        }
    }
});;
(function () {
    'use strict';
    app.filter('wbxShowAgeFilter', wbxDashFilter);

    wbxDashFilter.$inject = [];

    function wbxDashFilter() {
        return function (value) {
            if (value == null || value == '') {
                return value;
            }

            if (moment(value).isValid) {
                return value + " (Age=" + moment().diff(value, 'years') + ")";
            }
        }
    }

})();;
(function () {
    'use strict';
    app.filter('wbxSSNFilter', wbxSsnFilter);

    wbxSsnFilter.$inject = [];

    function wbxSsnFilter() {
        return function (value, mask) {
            if (value == null) {
                return value;
            }
            if (mask == null) {
                mask = true;
            }

            var result = value.trim().replace(/([-~!@#$%^&*()_+=`{}\[\]\|\\:;'<>,.\/? ])+/g, '');
            var len = 0;

            if (result != null) {
                len = result.length;
            }

            if (3 < len && len < 6) {
                if (mask) {
                    return "***-" + result.substr(3);
                }
                else {
                    return result.substr(0, 3) + "-" + result.substr(3);
                }
            }
            else if (len > 5) {
                if (mask) {
                    return "***-**-" + result.substr(5, 4);
                } else {
                    return result.substr(0, 3) + "-" + result.substr(3, 2) + "-" + result.substr(5, 4);
                }
            } else {
                return result;
            }
        }
    }
})();;
(function () {
    'use strict';
    app.filter('wbxTimeFilter', wbxTimeFilter);

    wbxTimeFilter.$inject = ['$filter'];

    function wbxTimeFilter($filter) {
        return function (value, isShowingSecond) {
            if (value == null || value == '') {
                return value;
            }
            else {
                var curTimeMoment = moment(value, moment.ISO_8601);
                if (!curTimeMoment.isValid() &&
                    value.indexOf("am") > -1 || value.indexOf("pm") > -1) {
                    curTimeMoment = moment(value, "hh:mm:ss a");
                }

                if (curTimeMoment.isValid()) {
                    if (isShowingSecond) {
                        return curTimeMoment.format("hh:mm:ss a");
                    }
                    else {
                        return curTimeMoment.format("hh:mm a");
                    }
                }
                else {
                    return null;
                }
            }
        };
    }

})();;
function formatMoney(c) {
    return parseFloat(c).toFixed(2);
};

app.directive('wbxConvertToNumber', function () {
    return {
        require: 'ngModel',
        link: function (scope, element, attrs, ngModel) {
            ngModel.$parsers.push(function (val) {
                return parseInt(val, 10);
            });
            ngModel.$formatters.push(function (val) {
                return angular.isDefined(val) ? '' + val : null;
            });
        }
    };
});


app.directive('enterAsTab', function ()
{
    return {
        restrict: 'A',
        link: function ($scope, elem, attrs)
        {
            elem.bind('keydown', function (e)
            {
                var code = e.keyCode || e.which;
                if (code === 13)
                {
                    e.preventDefault();
                    var ntabindex = parseFloat(elem[0].getAttribute('tabindex'));
                    var nextElem = null;
                    do 
                    {
                        if (e.shiftKey == false)
                        {
                            ntabindex++;
                        }
                        else
                        {
                            if (ntabindex > 1)
                                ntabindex--;
                        }

                        nextElem = $('[tabindex=' + ntabindex + ']');
                        if (nextElem != null)
                            nextElem.focus();
                        
                    } while (nextElem != null && nextElem.is(":visible") == false || nextElem.is(":disabled") == true)
                }
            });
        }
    }
});

app.directive('wbxEligibilitySearchCriteria', ['$http','$q','$timeout', function ($http, $q, $timeout) { 
    return {
        restrict: 'E',
        templateUrl: '/Templates/EligibilitySearchCriteria',
        require: '^form',
        scope: {
            searchData: '=searchCriteriaObject',
            clearSearchCriteria: '=',
            isDoneLoading: '=',
            requestToCreateMember: '=?',
            isCreateMemberMode: '=?',
            createMember: '&?',
            sessionInfo: '=?',
            additionalSearchCriteriaRequired: '='
        },
        controller: ['$scope', 'GoogleTagManagerService', function ($scope, googleTagManagerService) {
            $scope.clearSearchCriteria = false;
            $scope.searchCriteriaSessions = null;
            $scope.$watchCollection('[clearSearchCriteria, searchCriteriaSessions]', function (n, o) {
                if (n[0] != null && n[1] != null) {
                    $scope.resetMemberInfo();
                    $scope.clearSearchCriteria = false;
                }
            });

            $scope.initSearchCriteria = function () {
                if ($scope.sessionInfo == null) {
                    var promise = $scope.getSearchCriteriaSessions();
                    promise.then(function () {
                        $scope.populateSessionInfo();
                    }, function (data) {
                        // bad, do nothing
                    });
                }
                else {
                    $scope.searchCriteriaSessions = $scope.sessionInfo;
                    $scope.populateSessionInfo();
                }
            }

            $scope.populateSessionInfo = function () {
                    $scope.resetMemberInfo();
                    $scope.isDoneLoading = true;
                    if ($scope.searchData.passedInfo != null) {
                        //Populate some of the fields with passed info
                        if ($scope.searchData.passedInfo.RETAIN_MODE != 1) {
                            
                            $timeout(function () {
                                $scope.searchData.MemberInfoSelect = $scope.searchData.passedInfo.SEARCH_TYPE;

                                $scope.searchData.SUBSCRIBER_ID = $scope.searchData.passedInfo.SUBSCRIBER_ID;
                                $scope.searchData.LAST_NAME = $scope.searchData.passedInfo.LAST_NAME;
                                $scope.searchData.FIRST_NAME = $scope.searchData.passedInfo.FIRST_NAME;
                                $scope.searchData.DOB = $scope.searchData.passedInfo.DOB;
                                $scope.searchData.LAST_SSN = $scope.searchData.passedInfo.SSN;
                            });
                        }
                    }
            }

            $scope.MemberInfoChanged = function () {

                var radioButtonTitle = "";
                if($scope.searchData.MemberInfoSelect == "1"){
                    radioButtonTitle = "subscriber id";
                }
                else if($scope.searchData.MemberInfoSelect == "2"){
                    radioButtonTitle = "subscriber id and date of birth";
                }
                else if($scope.searchData.MemberInfoSelect == "3"){
                    radioButtonTitle = "last name and first name";
                }
                else if($scope.searchData.MemberInfoSelect == "4"){
                    radioButtonTitle = "last name and date of birth";
                }
                else if($scope.searchData.MemberInfoSelect == "5"){
                    radioButtonTitle = "last name, first name, and date of birth";
                }
                else if($scope.searchData.MemberInfoSelect == "6"){
                    radioButtonTitle = "last four(4) digits of SSN and date of birth";
                }
                else if($scope.searchData.MemberInfoSelect == "7"){
                    radioButtonTitle = "subscriber id, last name, first name, and date of birth";
                }

                googleTagManagerService.setClickInfo('click', 'verify member eligibility / start claim or authorization', radioButtonTitle + ' radio button', 'field_interaction', '', 'radio button', radioButtonTitle);

                $scope.clearMemberInfo();
            }

            $scope.clearMemberInfo = function () {
                $scope.searchData.SUBSCRIBER_ID = null;
                $scope.searchData.DOB = null;
                $scope.searchData.LAST_NAME = null;
                $scope.searchData.FIRST_NAME = null;
                $scope.searchData.LAST_SSN = null;
                $scope.additonalSearchFields = null;

                //Therapy
                $scope.searchData.IsSubscriberIdUnknown = false;
                $scope.isCreateMemberMode = false;
            }

            $scope.resetMemberInfo = function () {
                if ($scope.searchCriteriaSessions.SEARCH_SUBSCRIBER_ID_FLAG) {
                    $scope.searchData.MemberInfoSelect = 1;
                }
                else if ($scope.searchCriteriaSessions.SEARCH_SUBSCRIBER_ID_DOB_FLAG) {
                    $scope.searchData.MemberInfoSelect = 2;
                }
                else if ($scope.searchCriteriaSessions.SEARCH_LAST_FIRST_FLAG) {
                    $scope.searchData.MemberInfoSelect = 3;
                }
                else if ($scope.searchCriteriaSessions.SEARCH_LAST_DOB_FLAG) {
                    $scope.searchData.MemberInfoSelect = 4;
                }
                else if ($scope.searchCriteriaSessions.SEARCH_LAST_FIRST_DOB_FLAG) {
                    $scope.searchData.MemberInfoSelect = 5;
                }
                else if ($scope.searchCriteriaSessions.SEARCH_SSN_DOB_FLAG) {
                    $scope.searchData.MemberInfoSelect = 6;
                }
                else if ($scope.searchCriteriaSessions.SEARCH_SUBSCRIBER_ID_FIRST_LAST_DOB_FLAG) {
                    $scope.searchData.MemberInfoSelect = 7;
                }
                else {
                    $scope.searchData.MemberInfoSelect = 1;
                }

                $scope.clearMemberInfo();
            }

            $scope.getSearchCriteriaSessions = function () {
                var deferred = $q.defer();

                $http({
                    method: 'GET',
                    url: '/WebSession/GetSearchCriteriaSessions'
                }).then(function successCallback(response) {
                    $scope.searchCriteriaSessions = response.data;
                    deferred.resolve();
                }, function errorCallback(response) {
                    console.error(response.data.Message);
                    console.error(response);
                    if ($scope.ExceptionDialogControl != null) {
                        $scope.ExceptionDialogControl.showDialog("Error in getting search criteria sessions.");
                    }
                    else {
                        bootbox.alert(response.data.Message);
                    }
                    deferred.reject(false);
                });

                return deferred.promise;
            }

            //Therapy
            $scope.clearSubscriberId = function () {
                $scope.searchData.SUBSCRIBER_ID = null;
            }

            $scope.$watch('requestToCreateMember', function (n, o) {
                if (n) {
                    if ($scope.searchData.IsSubscriberIdUnknown) {
                        $scope.searchData.IsSubscriberIdUnknown = false;

                        $timeout(function () {
                            $('#SubscriberId6TextBox').focus();
                        });

                        $scope.search_form.$setSubmitted();
                        $scope.isCreateMemberMode = true;
                    }

                    $timeout(function () {
                        if ($scope.search_form.$invalid) {
                            if ($('.alert-danger:visible:first').offset()) {
                                $('html, body').animate({
                                    scrollTop: $('.alert-danger:visible:first').offset().top - 60
                                }, 750);
                            }
                        }
                        else {
                            $scope.createMember();
                        }
                    });

                    $scope.requestToCreateMember = false;
                }
            });

            $scope.$watch('additionalSearchCriteriaRequired',

              function () {

                  var allSearchFeildsFilled = ($scope.searchData.SUBSCRIBER_ID &&
                     $scope.searchData.LAST_NAME &&
                      $scope.searchData.FIRST_NAME &&
                      $scope.searchData.DOB &&
                      $scope.searchData.LAST_SSN);


                  if ($scope.additionalSearchCriteriaRequired && $scope.searchCriteriaSessions.SEARCH_LIMIT_RESULTS_TO_1 && allSearchFeildsFilled) {
                      $scope.MultpleResultsBanner = "Member could not be found. Please contact Customer Service.";
                  }
                  else if ($scope.additionalSearchCriteriaRequired && $scope.searchCriteriaSessions.SEARCH_LIMIT_RESULTS_TO_1) {
                      $scope.MultpleResultsBanner = "Please provide additional criteria.";
                      $scope.showAdditionalSearchCriteria();
                  }

              });


            $scope.showAdditionalSearchCriteria = function () {
                $scope.additonalSearchFields = {
                    SUBSCRIBER_ID: true,
                    LAST_NAME: true,
                    FIRST_NAME: true,
                    DOB: true,
                    LAST_SSN: true
                }

                var searchCriteria = parseInt($scope.searchData.MemberInfoSelect);

                switch (searchCriteria) {
                    case 1:
                        $scope.additonalSearchFields.SUBSCRIBER_ID = false;
                        break;
                    case 2:
                        $scope.additonalSearchFields.SUBSCRIBER_ID = false;
                        $scope.additonalSearchFields.DOB = false;
                        break;
                    case 3:
                        $scope.additonalSearchFields.LAST_NAME = false;
                        $scope.additonalSearchFields.FIRST_NAME = false;
                        break;
                    case 4:
                        $scope.additonalSearchFields.LAST_NAME = false;
                        $scope.additonalSearchFields.DOB = false;
                        break;
                    case 5:
                        $scope.additonalSearchFields.LAST_NAME = false;
                        $scope.additonalSearchFields.FIRST_NAME = false;
                        $scope.additonalSearchFields.DOB = false;
                        break;
                    case 6:
                        $scope.additonalSearchFields.LAST_SSN = false;
                        $scope.additonalSearchFields.DOB = false;
                        break;
                    case 7:
                        $scope.additonalSearchFields.SUBSCRIBER_ID = false;
                        $scope.additonalSearchFields.LAST_NAME = false;
                        $scope.additonalSearchFields.FIRST_NAME = false;
                        $scope.additonalSearchFields.DOB = false;
                        break;

                    default:
                        $scope.additonalSearchFields = {
                            SUBSCRIBER_ID: true,
                            LAST_NAME: true,
                            FIRST_NAME: true,
                            DOB: true,
                            LAST_SSN: true
                        }
                }
            }

        }],
        link: function (scope, element, attr, formController) {
            scope.search_form = formController;
        }
    };
}]);

app.directive('wbxUsernamePasswordPin', ['$http','$q','$timeout', function ($http, $q, $timeout) {
    return {
        restrict: 'E',
        template: "<div ng-include='usernamePasswordTemplate'></div>",
        require: '^form',
        scope: {
            registrationData: '=',
            clearFields: '=',
            isEdit: '=',
            showRequired : "=?"
        },
        controller: ['$scope', function ($scope) {
            $scope.clearFields = false;

            $scope.clearUserNameInfo = function () {
                $scope.registrationData.USER_NAME = null;
                $scope.registrationData.PASSWORD = null;
                $scope.registrationData.CONFIRM_PASSWORD = null;
            }

            $scope.$watch('clearFields', function (n, o) {
                if (n != null && n) {
                    $scope.clearUserNameInfo();
                    $scope.clearFields = false;
                }
            });

            $scope.$watch('isPasswordValid', function (n, o) {
                if (n != o && !$scope.isEdit) {
                    $scope.registration_form.passwordTextBox.$setValidity("notvalid", $scope.isPasswordValid);
                }
            });
        }],
        link: function (scope, element, attr, formController) {
            
            scope.usernamePasswordTemplate = "/Templates/UsernamePasswordPIN?showRequired=" + (scope.showRequired ? "true" : "false");
            scope.registration_form = formController;
        }
    };
}]);

app.directive('wbxPasswordStrength', function() {
    return {
        template: "<div class='wbx-progress'>"+
                  "<div class='progress-bar progress-bar-{{color}}' role='progressbar' ng-style='width'></div>"+
                  "</div>"+
                  "<span class='pull-right {{messageColor}}'>{{message}}</span>" + 
                  "<span aria-live='polite' role='{{pwd.length === 0 ? '' : 'alert'}}' class='sr-only'>{{message}} password</span>",
        restrict: 'A',
        scope: {
            pwd: '=wbxPasswordStrength'
        },
        link: function(scope /*, elem, attrs*/ ) {
            var
              mesureStrength = function(p) {
                  var matches = {
                      pos: {},
                      neg: {}
                  },
                    counts = {
                        pos: {},
                        neg: {
                            seqLetter: 0,
                            seqNumber: 0,
                            seqSymbol: 0
                        }
                    },
                    tmp,
                    strength = 0,
                    letters = 'abcdefghijklmnopqrstuvwxyz',
                    numbers = '01234567890',
                    symbols = '!#$%*~',
                    back,
                    forth,
                    i;

                  if (p) {
                      // Benefits
                      matches.pos.lower = p.match(/[a-z]/g);
                      matches.pos.upper = p.match(/[A-Z]/g);
                      matches.pos.numbers = p.match(/\d/g);
                      matches.pos.symbols = p.match(/[!#$%*~]+/g);
                      matches.pos.middleNumber = p.slice(1, -1).match(/\d/g);
                      matches.pos.middleSymbol = p.slice(1, -1).match(/[!#$%*~]+/g);

                      counts.pos.lower = matches.pos.lower ? matches.pos.lower.length : 0;
                      counts.pos.upper = matches.pos.upper ? matches.pos.upper.length : 0;
                      counts.pos.numbers = matches.pos.numbers ? matches.pos.numbers.length : 0;
                      counts.pos.symbols = matches.pos.symbols ? matches.pos.symbols.length : 0;

                      tmp = _.reduce(counts.pos, function(memo, val) {
                          // if has count will add 1
                          return memo + Math.min(1, val);
                      }, 0);

                      counts.pos.numChars = p.length;
                      tmp += (counts.pos.numChars >= 8) ? 1 : 0;

                      counts.pos.requirements = (tmp >= 3) ? tmp : 0;
                      counts.pos.middleNumber = matches.pos.middleNumber ? matches.pos.middleNumber.length : 0;
                      counts.pos.middleSymbol = matches.pos.middleSymbol ? matches.pos.middleSymbol.length : 0;

                      // Deductions
                      matches.neg.consecLower = p.match(/(?=([a-z]{2}))/g);
                      matches.neg.consecUpper = p.match(/(?=([A-Z]{2}))/g);
                      matches.neg.consecNumbers = p.match(/(?=(\d{2}))/g);
                      matches.neg.onlyNumbers = p.match(/^[0-9]*$/g);
                      matches.neg.onlyLetters = p.match(/^([a-z]|[A-Z])*$/g);

                      counts.neg.consecLower = matches.neg.consecLower ? matches.neg.consecLower.length : 0;
                      counts.neg.consecUpper = matches.neg.consecUpper ? matches.neg.consecUpper.length : 0;
                      counts.neg.consecNumbers = matches.neg.consecNumbers ? matches.neg.consecNumbers.length : 0;


                      // sequential letters (back and forth)
                      for (i = 0; i < letters.length - 2; i++) {
                          var p2 = p.toLowerCase();
                          forth = letters.substring(i, parseInt(i + 3));
                          back = _.str.reverse(forth);
                          if (p2.indexOf(forth) !== -1 || p2.indexOf(back) !== -1) {
                              counts.neg.seqLetter++;
                          }
                      }

                      // sequential numbers (back and forth)
                      for (i = 0; i < numbers.length - 2; i++) {
                          forth = numbers.substring(i, parseInt(i + 3));
                          back = _.str.reverse(forth);
                          if (p.indexOf(forth) !== -1 || p.toLowerCase().indexOf(back) !== -1) {
                              counts.neg.seqNumber++;
                          }
                      }

                      // sequential symbols (back and forth)
                      for (i = 0; i < symbols.length - 2; i++) {
                          forth = symbols.substring(i, parseInt(i + 3));
                          back = _.str.reverse(forth);
                          if (p.indexOf(forth) !== -1 || p.toLowerCase().indexOf(back) !== -1) {
                              counts.neg.seqSymbol++;
                          }
                      }

                      // repeated chars
                      counts.neg.repeated = _.chain(p.toLowerCase().split('')).
                      countBy(function(val) {
                          return val;
                      })
                        .reject(function(val) {
                            return val === 1;
                        })
                        .reduce(function(memo, val) {
                            return memo + val;
                        }, 0)
                        .value();

                      // Calculations
                      strength += counts.pos.numChars * 4;
                      if (counts.pos.upper) {
                          strength += (counts.pos.numChars - counts.pos.upper) * 2;
                      }
                      if (counts.pos.lower) {
                          strength += (counts.pos.numChars - counts.pos.lower) * 2;
                      }
                      if (counts.pos.upper || counts.pos.lower) {
                          strength += counts.pos.numbers * 4;
                      }
                      strength += counts.pos.symbols * 6;
                      strength += (counts.pos.middleSymbol + counts.pos.middleNumber) * 2;
                      strength += counts.pos.requirements * 2;

                      strength -= counts.neg.consecLower * 2;
                      strength -= counts.neg.consecUpper * 2;
                      strength -= counts.neg.consecNumbers * 2;
                      strength -= counts.neg.seqNumber * 3;
                      strength -= counts.neg.seqLetter * 3;
                      strength -= counts.neg.seqSymbol * 3;

                      if (matches.neg.onlyNumbers) {
                          strength -= counts.pos.numChars;
                      }
                      if (matches.neg.onlyLetters) {
                          strength -= counts.pos.numChars;
                      }
                      if (counts.neg.repeated) {
                          strength -= (counts.neg.repeated / counts.pos.numChars) * 10;
                      }
                  }

                  return Math.max(0, Math.min(100, Math.round(strength)));
              },


              getClass = function(s) {
                  switch (Math.round(s / 33)) {
                      case 0:
                          return 'default';
                      case 1:
                          return 'danger';
                      case 2:
                          return 'warning';
                      case 3:
                          return 'success';
                  }
              },
            
              getText = function (s) {
                  switch (Math.round(s / 33)) {
                      case 0:
                          return 'No Strength';
                      case 1:
                          return 'Weak';
                      case 2:
                          return 'Medium';
                      case 3:
                          return 'Very Strong';
                  }
              },

              getTextClass = function (s) {
                  switch (Math.round(s / 33)) {
                      case 0:
                          return 'wbx-text-grey';
                      case 1:
                          return 'wbx-progress-danger-color';
                      case 2:
                          return 'wbx-progress-warning-color';
                      case 3:
                          return 'wbx-progress-success-color';
                  }
              },

            getBarLength = function (s) {
                switch (Math.round(s / 33)) {
                    case 0:
                        return { 'width': '5%' };
                    case 1:
                        return { 'width': '33%' };
                    case 2:
                        return { 'width': '66%' };
                    case 3:
                        return { 'width': '100%' };
                }
            }

            scope.$watch('pwd', function() {
                scope.value = mesureStrength(scope.pwd);
                scope.color = getClass(scope.value);
                scope.message = getText(scope.value);
                scope.messageColor = getTextClass(scope.value);
                scope.width = getBarLength(scope.value);
            });

        },
    };
});

app.directive('wbxPasswordStrengthDisplay', function () {
    return {
        templateUrl: '/Templates/PasswordStrengthDisplay',
        restrict: 'A',
        scope: {
            pwd: '=wbxPsdPassword',
            userName: '=wbxPsdUserName',
            isPasswordValid: '=wbxPsdIsValid'
        },
        controller: ['$scope','$http', '$location', function PasswordDisplayController($scope, $http, $location) {

            $scope.rules = [];

            $scope.Init = function (userName) {

                if ((userName == undefined) || (userName == null))
                    userName = "";

                // Get the policy rules
                $http({
                    url: '/AccountManagement/GetPasswordRules',
                    method: 'GET',
                    params: { userName: userName }
                }).then(function successCallback(response) {
                    if (response.data.length == 0) {
                        if ($scope.ExceptionDialogControl != null) {
                            $scope.ExceptionDialogControl.showDialog("Error with getting password rules.");
                        }
                        else {
                            bootbox.alert("Could not retrieve password rules.");
                        }
                    }
                    else {
                        $scope.rules = response.data;
                    }
                }, function errorCallback(response) {
                    console.error(response.data.Message);
                    console.error(response);
                    if ($scope.ExceptionDialogControl != null) {
                        $scope.ExceptionDialogControl.showDialog("Error with getting password rules.");
                    }
                    else {
                        bootbox.alert("Could not retrieve password rules.");
                    }

                });
            }

        }],
        link: function (scope, element, attributes, controller, transcludeFn) {
            
            var lower = [];
            var upper = [];
            var numbers = [];
            var symbols = [];
            var passwordLength = 0;
            
            scope.Init(scope.userName);

            var characterTest = function (p) {

            },


            CheckForRequiredChars = function (p) {

                if (p == undefined)
                {
                    //This is to makes sure the checkmarks are removed if the password is deleted
                    lower = null;
                    upper = null;
                    numbers = null;
                    symbols = null;
                    passwordLength = 0;
                    return;
                }
                else {
                    lower = p.match(/[a-z]/g);
                    upper = p.match(/[A-Z]/g);
                    numbers = p.match(/\d/g);
                    symbols = p.match(/[!#$%*~]+/g);
                    passwordLength = p.length;
                }
            },


            DisplayCheckmarks = function () {
                var count = scope.rules.length;
                var checkedCount = 0;
                for (var i = 0; i < count; i++) {
                    // Special characters
                    if (scope.rules[i].character == "s") {
                        if (symbols != null) {
                            scope.rules[i].requirementMet = true;
                            checkedCount++;
                        }
                        else {
                            scope.rules[i].requirementMet = false;
                        }
                        continue;
                    }
                    // Upper case letters
                    if (scope.rules[i].character == "u") {
                        if (upper != null) {
                            scope.rules[i].requirementMet = true;
                            checkedCount++;
                        }
                        else {
                            scope.rules[i].requirementMet = false;
                        }
                        continue;
                    }
                    // Numeric characters
                    if (scope.rules[i].character == "n") {
                        if (numbers != null) {
                            scope.rules[i].requirementMet = true;
                            checkedCount++;
                        }
                        else {
                            scope.rules[i].requirementMet = false;
                        }
                        continue;
                    }
                    // Lower or Upper (alpha) case letters
                    if (scope.rules[i].character == "l") {
                        if (lower != null || upper != null) {
                            scope.rules[i].requirementMet = true;
                            checkedCount++;
                        }
                        else {
                            scope.rules[i].requirementMet = false;
                        }
                        continue;
                    }
                    // Minimum password length
                    if (scope.rules[i].character == "g") {
                        if (passwordLength >= scope.rules[i].passwordLength) {
                            scope.rules[i].requirementMet = true;
                            checkedCount++;
                        }
                        else {
                            scope.rules[i].requirementMet = false;
                        }
                        continue;
                    }

                    if (scope.rules[i].character == "r") {
                        // Can't contain user name
                        var password = new String(scope.pwd);
                        if ((scope.userName != "") && (scope.userName != undefined))
                            var userName = scope.userName;
                        else {
                            var userName = new String(scope.rules[i].userName);
                        }

                        if ((scope.pwd != "") && (scope.pwd != undefined)) {
                            var result = password.toLowerCase().indexOf(userName.toLowerCase());
                            if (result == -1) {
                                scope.rules[i].requirementMet = true;
                                checkedCount++;
                            }
                            else {
                                scope.rules[i].requirementMet = false;
                            }
                        }
                        else {
                            scope.rules[i].requirementMet = false;
                        }

                        continue;
                    }

                }
                scope.isPasswordValid = (count == checkedCount);

            };


            scope.$watchCollection('[userName, pwd]', function (n, o) {
                if (n[0] != o[0] || n[1] != o[1]) {
                    CheckForRequiredChars(scope.pwd);
                    DisplayCheckmarks();
                }
            });

        },
    };
});

app.directive('wbxMemberAction', ['$window', '$timeout', '$http', '$location', '$q', '$sce', function ($window, $timeout, $http, $location, $q, $sce) {
    return {
        restrict: 'E',
        templateUrl: '/Templates/MemberAction',
        scope: {
            selectedItem: '=',
            productLevelResults: '=?',
            openClose: '=',
            pageSource: '=',
            isCalendar: '=?',
            isDental: '=?',
            isAddedToRoster: '=?',
            isAddedToCalendar: '=?',
            closeMemberAction: '&?'
        },
        controller: ['$scope', 'ImpersonateService', 'GoogleTagManagerService', 'FeatureFlagService', function ($scope, impersonateService, googleTagManagerService, featureFlagService) {

          $scope.$watch('openClose', function (n, o) {
                if (n != o && n != null && n) {

                    $scope.evaluateStartClaimButtonForTherapy();

                    //open the dialog
                    $('#MemberAction' + $scope.MemberActionId + 'Dialog').modal({
                        backdrop: 'static'
                    })
                    $('#MemberAction' + $scope.MemberActionId + 'Dialog').modal('show');
                    $scope.openClose = false;
                    
                }
            });
            $scope.init = function () {
                  impersonateService.getImpersonateSessionInfo()
               .then(function (response) {
                   $scope.isImpersonation = response.IsImpersonation;
                    $scope.impersonatedName = response.ImpersonatedName;
                });

                featureFlagService.getFeatureFlagsForPWPDentalBenefitSummaryReport()
                    .then(function (response) {
                        $scope.isPwpDentalBenefitSummaryReportEnabled = response.IsPwpDentalBenefitSummaryReportEnabled;
                        $scope.showBenefitSummaryLink = response.ShowBenefitSummaryLink;
                    });
            };

            $scope.modalActionClass = function (isMultiple) {
                //Determines the size of the modal action window depending if it's a single or multiple products.
                if (isMultiple)
                    return 'modal-lg';
                else
                    return '';
            }

            $scope.startClaimAuth = function (type, auth) {

                var buttontitle = "";
                if(type == 1){
                    buttontitle = 'a claim';
                }
                if(type == 2){
                    buttontitle = 'an authorization';
                }

                googleTagManagerService.setClickInfo('click', 'verify member eligibility / start claim or authorization', 'patient selected - start ' + buttontitle + ' button', 'field_interaction', '', 'button', 'start ' + buttontitle);

                $('#MemberAction' + $scope.MemberActionId + 'Dialog').modal('hide');
                $http({
                    url: "/Welcome/SetHomePageData",
                    method: "PUT",
                    data: {
                        LOCATION_ID: $scope.selectedItem.LOCATION_ID,
                        PROVIDER_ID: $scope.selectedItem.PROVIDER_ID,
                        DATE_OF_SERVICE: $scope.selectedItem.DATE_OF_SERVICE,
                        SUBSCRIBER_ID: $scope.selectedItem.SUBSCRIBER_ID,
                        FIRST_NAME: $scope.selectedItem.FIRST_NAME,
                        LAST_NAME: $scope.selectedItem.LAST_NAME,
                        DOB: $scope.selectedItem.DOB,
                        DATA_SOURCE: $scope.pageSource,
                        MEMBER_ID: $scope.selectedItem.MEMBER_ID,
                        PRODUCT_ID: $scope.selectedItem.PRODUCT_ID,
                        INSURER_ID: $scope.selectedItem.INSURER_ID,
                        ENROLLEE_ID: $scope.selectedItem.ENROLLEE_ID,
                        AUTHORIZATION_NUMBER: auth != null ? auth.AUTHORIZATION_NUMBER : null
                    }
                }).then(function successCallback(response) {
                    if (!response.data.Status) {
                        console.error(response.data.Message);
                        console.error(response);
                        if ($scope.ExceptionDialogControl != null) {

                            googleTagManagerService.setClickInfo('error', 'verify member eligibility / start claim or authorization', 'patient selected - start ' + buttontitle + ' button', 'field_interaction', 'error with setting homepage data', 'button', 'start ' + buttontitle);

                            $scope.ExceptionDialogControl.showDialog("Error with setting homepage data.");
                        }
                        else {
                            googleTagManagerService.setClickInfo('error', 'verify member eligibility / start claim or authorization', 'patient selected - start ' + buttontitle + ' button', 'field_interaction', ((response.data.Message) ? response.data.Message.toLowerCase() : "an error has occurred"), 'button', 'start ' + buttontitle);

                            bootbox.alert(response.data.Message);
                        }
                    }
                    else {

                        googleTagManagerService.setClickInfo('success', 'verify member eligibility / start claim or authorization', 'patient selected - start ' + buttontitle + ' button', 'field_interaction', 'start ' + buttontitle + ' generated successfully', 'button', 'start ' + buttontitle);

                        var index = $location.absUrl().indexOf("/PatientManagement");
                        var url = "";
                        if (index > 0) {
                            url = $location.absUrl().substr(0, index);
                        }
                        else {
                            url = $location.absUrl();
                        }

                        index = url.indexOf("#");
                        if (index > 0) {
                            url = url.substr(0, index);
                        }

                        if (type == 1) {
                            $window.location.href = url + '/ClaimEntry';
                        }
                        else {
                            $window.location.href = url + '/AuthEntry';
                        }
                    }
                }, function errorCallback(response) {
                    console.error(response.data.Message);
                    console.error(response);
                    if ($scope.ExceptionDialogControl != null) {

                        googleTagManagerService.setClickInfo('error', 'verify member eligibility / start claim or authorization', 'patient selected - start ' + buttontitle + ' button', 'field_interaction', 'error with setting homepage data', 'button', 'start ' + buttontitle);

                        $scope.ExceptionDialogControl.showDialog("Error with setting homepage data.");
                    }
                    else {
                        googleTagManagerService.setClickInfo('error', 'verify member eligibility / start claim or authorization', 'patient selected - start ' + buttontitle + ' button', 'field_interaction', ((response.data.Message) ? response.data.Message.toLowerCase() : "an error has occurred"), 'button', 'start ' + buttontitle);

                        bootbox.alert(response.data.Message);
                    }
                });
            }

            $scope.closeMemberActionDialog = function () {

                googleTagManagerService.setClickInfo('click', 'verify member eligibility / start claim or authorization', 'patient selected - close icon', 'close_modal', '', 'icon', 'close icon');

                $('#MemberAction' + $scope.MemberActionId + 'Dialog').modal('hide');
                $scope.closeMemberAction();
            }

            $scope.multiProductStartClaimAuth = function (productInfo, type) {
                $scope.selectedItem.SUBSCRIBER_ID = productInfo.SUBSCRIBER_ID;
                $scope.selectedItem.INSURER_ID = productInfo.INSURER_ID;
                $scope.selectedItem.PRODUCT_ID = productInfo.PRODUCT_ID;
                $scope.selectedItem.MEMBER_ID = productInfo.MEMBER_ID;
                $scope.startClaimAuth(type);
            }

            $scope.showEligibilityReport = function () {

                googleTagManagerService.setClickInfo('click', 'verify member eligibility / start claim or authorization', 'patient selected - view eligibility report button', 'field_interaction', '', 'button', 'view eligibility report');

                var googletaginfo = {
                    "attribute1": 'verify member eligibility / start claim or authorization',
                    "attribute2": 'patient selected - view eligibility report button',
                    "attribute3": 'field_interaction',
                    "attribute4": 'eligibility report generated successfully',
                    "category": 'button',
                    "label": 'view eligibility report',
                }

                var sessionProperties = $scope.setSessionPropertiesForEligibilityReport();
                
                $scope.openTab("/Areas/PWP/Reports/PortalEligibility.aspx", sessionProperties, googletaginfo);
            }

            $scope.setSessionPropertiesForEligibilityReport = function () {
                var sessionProperties = [];
                var sessionProperty = {
                    SESSION_NAME: "REPORT_PORTAL_ELIGIBILITY_ENROLLEE_ID",
                    SESSION_VALUE: $scope.selectedItem.ENROLLEE_ID
                }
                sessionProperties.push(sessionProperty);

                var sessionProperty = {
                    SESSION_NAME: "REPORT_PORTAL_ELIGIBILITY_SUBSCRIBER_ID",
                    SESSION_VALUE: $scope.selectedItem.SUBSCRIBER_ID
                }
                sessionProperties.push(sessionProperty);

                var sessionProperty = {
                    SESSION_NAME: "REPORT_PORTAL_ELIGIBILITY_PROVIDER_ID",
                    SESSION_VALUE: $scope.selectedItem.PROVIDER_ID
                }
                sessionProperties.push(sessionProperty);

                var sessionProperty = {
                    SESSION_NAME: "REPORT_PORTAL_ELIGIBILITY_LOCATION_ID",
                    SESSION_VALUE: $scope.selectedItem.LOCATION_ID
                }
                sessionProperties.push(sessionProperty);

                var sessionProperty = {
                    SESSION_NAME: "REPORT_PORTAL_ELIGIBILITY_PRODUCT_ID",
                    SESSION_VALUE: $scope.selectedItem.PRODUCT_ID
                }
                sessionProperties.push(sessionProperty);

                var sessionProperty = {
                    SESSION_NAME: "REPORT_PORTAL_ELIGIBILITY_STATUS",
                    SESSION_VALUE: $scope.selectedItem.STATUS
                }
                sessionProperties.push(sessionProperty);

                var sessionProperty = {
                    SESSION_NAME: "REPORT_PORTAL_ELIGIBILITY_DATE_OF_SERVICE",
                    SESSION_VALUE: $scope.selectedItem.DATE_OF_SERVICE
                }
                sessionProperties.push(sessionProperty);

                return sessionProperties;
            }

            $scope.multiProdutShowEligibilityReport = function (productInfo) {
                $scope.selectedItem.SUBSCRIBER_ID = productInfo.SUBSCRIBER_ID;
                $scope.selectedItem.PRODUCT_ID = productInfo.PRODUCT_ID;
                $scope.selectedItem.STATUS = productInfo.STATUS;
                $scope.showEligibilityReport();
            }

            $scope.displayBenefitSummaryRdl = function(googletaginfo){
               var sessionProperties = $scope.setSessionPropertiesForPortalBenefitSummaryReport();
                $timeout(function ()
                    {
                    $scope.openTab("/Areas/PWP/Reports/PortalBenefitSummaryReport.aspx", sessionProperties, googletaginfo);
                    }, 250);
            }

             $scope.setSessionPropertiesForPortalBenefitSummaryReport = function () {
                var sessionProperties = [];
                var sessionProperty = {
                    SESSION_NAME: "REPORT_PORTAL_BENEFIT_SUMMARY_DATE_OF_SERVICE",
                    SESSION_VALUE: $scope.selectedItem != undefined ? $scope.selectedItem.DATE_OF_SERVICE : ''
                }
                sessionProperties.push(sessionProperty);

                var sessionProperty = {
                    SESSION_NAME: "REPORT_PORTAL_BENEFIT_SUMMARY_PRODUCT_ID",
                    SESSION_VALUE: $scope.selectedItem != undefined ? $scope.selectedItem.PRODUCT_ID : '' 
                }
                sessionProperties.push(sessionProperty);

                var sessionProperty = {
                    SESSION_NAME: "REPORT_PORTAL_BENEFIT_SUMMARY_ENROLLEE_ID",
                    SESSION_VALUE:  $scope.selectedItem != undefined ? $scope.selectedItem.ENROLLEE_ID : '' 
                }
                sessionProperties.push(sessionProperty);

                return sessionProperties;
            }


            $scope.showPortalBenefitSummaryReport = function () {

                googleTagManagerService.setClickInfo('click', 'verify member eligibility / start claim or authorization', 'patient selected - view benefits link', 'field_interaction', '', 'link', 'view benefits');

                var googletaginfo = {
                    "attribute1": 'verify member eligibility / start claim or authorization',
                    "attribute2": 'patient selected - view benefits link',
                    "attribute3": 'field_interaction',
                    "attribute4": 'benefits summary generated successfully',
                    "category": 'link',
                    "label": 'view benefits',
                }

                if($scope.isDental && $scope.isPwpDentalBenefitSummaryReportEnabled && $scope.showBenefitSummaryLink){
                    $scope.loadBenefitSummaryReportData(googletaginfo);
                    $('#BenefitSummaryReportModal').modal('show');
                 }
                else
                {
                    $scope.displayBenefitSummaryRdl(googletaginfo);
                    return;
                 }           
            }
            
            $scope.setInitalSessionValues = function(sessionProperties){
                sessionProperties[0].SESSION_VALUE == undefined ? sessionProperties[0].SESSION_VALUE= null : sessionProperties[0].SESSION_VALUE;
                sessionProperties[1].SESSION_VALUE == undefined ? sessionProperties[1].SESSION_VALUE=0 : sessionProperties[1].SESSION_VALUE;
                sessionProperties[2].SESSION_VALUE == undefined ? sessionProperties[2].SESSION_VALUE=0 : sessionProperties[2].SESSION_VALUE;
            }

            $scope.loadBenefitSummaryReportData = function(googletaginfo){
            $scope.loadingCoinsurance = true;
            $scope.loadingForPrint = false;
            let sessionProperties = $scope.setSessionPropertiesForPortalBenefitSummaryReport();
            $scope.setInitalSessionValues(sessionProperties);
           
                let productId = parseInt(sessionProperties[1].SESSION_VALUE);
                let enrolleeId = parseInt(sessionProperties[2].SESSION_VALUE);
                
                $scope.currentProductPeriod = $scope.currentProductPeriod == undefined ? 0 : $scope.currentProductPeriod
                productId = isNaN(productId) ? 0 : productId; 
                enrolleeId = isNaN(enrolleeId) ? 0 : enrolleeId;
                let promise = $scope.getBenefitSummaryreportData(productId, enrolleeId);  
                promise.then(function (r)
                {
                    let memberData = $scope.getBenefitSummaryreportMemberHeaderData(productId, enrolleeId, googletaginfo);
                    memberData.then(function ()
                    { 
                        let coninsuranceData  = $scope.getBenefitSummaryCoinsurance($scope.currentProductPeriod, productId);                                
                        coninsuranceData.then(function ()
                        {              
                            let productPeriodData = $scope.getBenefitSummaryCopayAmounts($scope.currentProductPeriod, productId);
                            productPeriodData.then(function ()
                            {                               
                                $scope.resetBenefitSummaryModal();
                                $scope.loadingCoinsurance = false;
                            });

                        });
                    });             
                }); 
            }

        $scope.resetBenefitSummaryModal = function(){
            document.getElementById('#BenefitSummaryReportTabsgeneralInfoTabTab').className ="active active";
            document.getElementById('BenefitSummaryReportTabsgeneralInfoTabPanel').className ="active tab-pane";
                     
            document.getElementById('#BenefitSummaryReportTabsserviceLimitationsTabTab').className ="";
                        
            if(document.getElementById('BenefitSummaryReportTabsserviceLimitationsTabPanel') != null){
                document.getElementById('BenefitSummaryReportTabsserviceLimitationsTabPanel').className ="tab-pane";
            }
  
            document.getElementById('#BenefitSummaryReportTabscoveredServicesTabTab').className="";
            if( document.getElementById('BenefitSummaryReportTabscoveredServicesTabPanel') != null)
            {
                document.getElementById('BenefitSummaryReportTabscoveredServicesTabPanel').className="tab-pane";
            }
        }
            
            $scope.getBenefitSummaryreportData = function(productId, enrolleeId)
            {
                $scope.benefitSummaryDataOON=[];
               
                var deferred = $q.defer();
                var sessionProperties = $scope.setSessionPropertiesForPortalBenefitSummaryReport();
                $scope.setInitalSessionValues(sessionProperties);
               
                            $http({
                                method: 'GET',
                                url: '/PWP/BenefitSummaryReport/GetBenefitSummaryReport',
                            params: {productId: productId,
                                     enrolleeId: enrolleeId}
                            }).then(function (data) {
                                $scope.benefitSummaryData = data.data;
                                if($scope.benefitSummaryData.length >0){
                                    angular.copy($scope.benefitSummaryData,$scope.benefitSummaryDataOON);
                                    $scope.benefitSummaryDataOON = $scope.benefitSummaryDataOON.filter(function (item) { return item.OON_FLAG == 1 });
                                    $scope.benefitSummaryData = $scope.benefitSummaryData.filter(function (item) { return item.OON_FLAG ==  0});
                                }
                                deferred.resolve(true);    
                            });
                  return deferred.promise;         
            }

            $scope.getBenefitSummaryreportMemberHeaderData = function(productId, enrolleeId, googletaginfo)
            {

                googletaginfo = googletaginfo || "notag";

                $scope.ELIGIBLE = 1;
                $scope.NOT_ELIGIBLE = 2;
                $scope.ELIGIBLE_STARTING = 3;
                $scope.ELIGIBLE_ENDING = 4;

                var deferred = $q.defer();
                $scope.benefitSummaryMemberHeaderData=[];
                var sessionProperties = $scope.setSessionPropertiesForPortalBenefitSummaryReport();
                productId = isNaN(productId) ? 0 : productId;

                        $http({
                            method: 'GET',
                            url: '/PWP/BenefitSummaryReport/GetBenefitSummaryReportMemberData',
                        params: {productId: productId,
                                 enrolleeId: parseInt(enrolleeId),
                                 dateOfService : sessionProperties[0].SESSION_VALUE}
                        }).then(function (data) {

                            if (googletaginfo != "notag") {
                                googleTagManagerService.setClickInfo('success', googletaginfo.attribute1, googletaginfo.attribute2, googletaginfo.attribute3, googletaginfo.attribute4, googletaginfo.category, googletaginfo.label);
                            }

                            $scope.benefitSummaryMemberHeaderData = data.data; 
                            $scope.currentProductPeriod = $scope.benefitSummaryMemberHeaderData.PRODUCT_PERIOD;
                            deferred.resolve(true);          
                        }, function errorCallback(response) {

                            if (googletaginfo != "notag") {
                                googleTagManagerService.setClickInfo('error', googletaginfo.attribute1, googletaginfo.attribute2, googletaginfo.attribute3, 'error geeting benefits summary report', googletaginfo.category, googletaginfo.label);
                            }                 
                        });

                    $scope.clearCodeSearchResults();
                    return deferred.promise;
            }
                
            $scope.getCoveredServices = function()
            {
              var deferred = $q.defer();
                $scope.benefitSummaryCoveredServicesData=[];
                var sessionProperties = $scope.setSessionPropertiesForPortalBenefitSummaryReport(); 
                var productId = parseInt(sessionProperties[1].SESSION_VALUE);
                productId = isNaN(productId) ? 0 : productId;         
                        $http({
                            method: 'GET',
                            url: '/PWP/BenefitSummaryReport/GetBenefitSummaryCoveredServices',
                        params: {productId: productId,
                                 enrolleeId: parseInt(sessionProperties[2].SESSION_VALUE),
                                 dateOfService : sessionProperties[0].SESSION_VALUE}
                        }).then(function (data) {
                            $scope.benefitSummaryCoveredServicesData = data.data; 
                      
                            deferred.resolve(true);          
                        });

                    return deferred.promise;
            }
  
            $scope.closeBenefitSummaryModal = function(){
                $scope.clearCodeSearchResults();
                $('#BenefitSummaryReportModal').modal('hide');
            }

            $scope.getBenefitSummaryCoinsurance = function (productPeriod, productId) {            
                $scope.benefitSummaryCoinsuranceData = [];
                $scope.benefitSummaryCoinsuranceDataOON=[];
                $scope.coinsuranceCodeGroups = [];
                $scope.coinsuranceCodeGroupsOOA = [];
                $scope.hasCoinsurance = false;
                $scope.hasCoinsuranceOON = false;
                let sessionProperties = $scope.setSessionPropertiesForPortalBenefitSummaryReport();
                $scope.setInitalSessionValues(sessionProperties);
                 var deferred = $q.defer();
               
                        $http({
                            method: 'GET',
                            url: '/PWP/BenefitSummaryReport/GetBenefitSummaryReportCoinsuranceData',
                        params: {productId: productId,
                                 productPeriod: productPeriod}
                        }).then(function (data) {
                            $scope.benefitSummaryCoinsuranceData = data.data; 
                            if($scope.benefitSummaryCoinsuranceData.length >0){
                             angular.copy($scope.benefitSummaryCoinsuranceData, $scope.benefitSummaryCoinsuranceDataOON);
                             $scope.benefitSummaryCoinsuranceDataOON = $scope.benefitSummaryCoinsuranceDataOON.filter(function (item) { return item.OON_FLAG == 1 });
                             $scope.benefitSummaryCoinsuranceData = $scope.benefitSummaryCoinsuranceData.filter(function (item) { return item.OON_FLAG ==  0});
                          
                              if($scope.benefitSummaryCoinsuranceData.length >0){
                                $scope.coinsuranceCodeGroups = $scope.benefitSummaryCoinsuranceData.reduce((acc, cur) => [
                                ...acc.filter((obj) => obj.CODE_GROUP !== cur.CODE_GROUP), cur
                                                ], []);
                                }

                            if($scope.benefitSummaryCoinsuranceDataOON.length >0){
                                $scope.coinsuranceCodeGroupsOOA = $scope.benefitSummaryCoinsuranceDataOON.reduce((acc, cur) => [
                                ...acc.filter((obj) => obj.CODE_GROUP !== cur.CODE_GROUP), cur
                                                ], []);
                                }                      
                            }
                            $scope.hasCoinsurance = $scope.benefitSummaryCoinsuranceData.length >0;  ;
                            $scope.hasCoinsuranceOON = $scope.benefitSummaryCoinsuranceDataOON.length >0;  ;
                            deferred.resolve(true);          
                        });

                    return deferred.promise;
            }

            $scope.getServiceLimitations = function () {
                var promise = $scope.getServiceLimitationsData();
                promise.then(function (r)
                {
                    $scope.getBenefitSummaryWaitingPeriods();
                });
            }

            $scope.getServiceLimitationsData = function(){

                var deferred = $q.defer();
                var LIMITATION_BY_CODE = 1;
                var LIMITATION_BY_CODESET = 3;
                $scope.benefitSummaryServiceLimitations = [];
                $scope.serviceLimitationsByCode = [];
                $scope.serviceLimitationsByCodeSet = [];
                $scope.serviceLimitationsByAge=[];
                var deferred = $q.defer();
                var sessionProperties = $scope.setSessionPropertiesForPortalBenefitSummaryReport();
                $scope.setInitalSessionValues(sessionProperties);
                var productId = parseInt(sessionProperties[1].SESSION_VALUE);
                productId = isNaN(productId) ? 0 : productId;
           
                        $http({
                            method: 'GET',
                            url: '/PWP/BenefitSummaryReport/GetBenefitSummaryServiceLimitationsData',
                            params: {
                                 productId: productId,
                                 enrolleeId: parseInt(sessionProperties[2].SESSION_VALUE)}
                                }).then(function (data) {
                                            $scope.benefitSummaryServiceLimitations = data.data;     
                                            angular.copy($scope.benefitSummaryServiceLimitations,$scope.serviceLimitationsByCode);  
                                            angular.copy($scope.benefitSummaryServiceLimitations,$scope.serviceLimitationsByCodeSet); 
                                            $scope.serviceLimitationsByCode = $scope.serviceLimitationsByCode.filter(function (item) { return item.LIMITATION_TYPE == LIMITATION_BY_CODE });
                                            $scope.serviceLimitationsByCodeSet = $scope.serviceLimitationsByCodeSet.filter(function (item) { return item.LIMITATION_TYPE == LIMITATION_BY_CODESET });
                                            $scope.serviceLimitationsByCodeSet.sort(function(a, b) {
                                                return parseFloat(a.AGE_MIN) - parseFloat(b.AGE_MIN);
                                            });
                                            $scope.serviceLimitationsByAge = $scope.serviceLimitationsByCodeSet.reduce((acc, cur) => [
                                                ...acc.filter((obj) => obj.FREQUENCY != cur.FREQUENCY || obj.DESCRIPTION_SHORT != cur.DESCRIPTION_SHORT), cur
                                            ], []);
                                            deferred.resolve(true);          
                                        });
                    return deferred.promise;

            }

            $scope.getBenefitSummaryWaitingPeriods = function(){
                $scope.loadingWaitingPeriods = false;
                $scope.waitingPeriodCodesets = [];
                $scope.waitingPeriodsCodesByCodeSet = [];
                $scope.benefitSummaryWaitingPeriods = [];

                var deferred = $q.defer();
                var sessionProperties = $scope.setSessionPropertiesForPortalBenefitSummaryReport();
                $scope.setInitalSessionValues(sessionProperties);
                var productId = parseInt(sessionProperties[1].SESSION_VALUE);
                productId = isNaN(productId) ? 0 : productId;

                $scope.loadingWaitingPeriods = true;
                        $http({
                            method: 'GET',
                            url: '/PWP/BenefitSummaryReport/GetBenefitSummaryWaitingPeriods',
                            params: {
                                 productId:  productId,
                                 enrolleeId: parseInt(sessionProperties[2].SESSION_VALUE)}
                                }).then(function (data) {
                                            $scope.benefitSummaryWaitingPeriods = data.data;
                                            $scope.hasWaitingPeriods = $scope.benefitSummaryWaitingPeriods.length >0;      
                                            angular.copy($scope.benefitSummaryWaitingPeriods,$scope.waitingPeriodCodesets);  
                                            angular.copy($scope.benefitSummaryWaitingPeriods,$scope.waitingPeriodsCodesByCodeSet); 
                                            $scope.waitingPeriodCodesets = $scope.waitingPeriodCodesets.reduce((acc, cur) => [
                                                ...acc.filter((obj) => obj.CODESET_ID !== cur.CODESET_ID), cur
                                            ], []);

                                            deferred.resolve(true);          
                                        });
                    $scope.loadingWaitingPeriods = false;                  
                    return deferred.promise;
            }            

            $scope.getBenefitSummaryCopayAmounts = function (productPeriod, productId) {
                $scope.benefitSummaryCopays = [];
                $scope.benefitSummaryCopaysOOA = [];
                $scope.hasCopays = false;
                $scope.hasCopaysOON = false;
                var deferred = $q.defer();              
                var sessionProperties = $scope.setSessionPropertiesForPortalBenefitSummaryReport(productPeriod);
                
                  $http({
                        method: 'GET',
                        url: '/PWP/BenefitSummaryReport/GetBenefitSummaryReportCopayData',
                        params: {
                                productId: productId,
                                productPeriod: productPeriod}
                            }).then(function (data) {
                                        $scope.benefitSummaryCopays = data.data;
                                        if($scope.benefitSummaryCopays.length >0){
                                            angular.copy($scope.benefitSummaryCopays,$scope.benefitSummaryCopaysOOA);
                                            $scope.benefitSummaryCopaysOOA = $scope.benefitSummaryCopaysOOA.filter(function (item) { return item.OON_FLAG == 1 });
                                            $scope.benefitSummaryCopays = $scope.benefitSummaryCopays.filter(function (item) { return item.OON_FLAG == 0 });
                                            $scope.hasCopays = $scope.benefitSummaryCopays.length >0;      
                                            $scope.hasCopaysOON = $scope.benefitSummaryCopaysOOA.length >0;
                                        }    
                                        deferred.resolve(true);          
                                        });
                           
                    $scope.loadingCoinsurance = false;            
                    return deferred.promise;
            }

            $scope.printDownloadSummary = function(){
            var printOutput = ""; 
            $scope.loadingForPrint = false;
                      
            var style="<style>.generalInfoResultsTable td {"
            style +="line-height: 25px;"
            style +="padding: 10px;"
            style +="border-style: solid;"
            style +="border-width: thin;"
            style +="border-color: #9d9696;"
            style +="}"
            style +=".generalInfoResults{"
            style +="height:35px;"
            style +="}"
            style +=".itemAmount{"
            style +="color:#334CA0FD"
            style +="}"
            style +=" html, body {"
            style +="max-width: 100%;"
            style +="} ";
            style += "@media print {";
            style += "body {";
            style += "margin-top: 5px";
            style += "margin-left: 0px";
            style += "transform: scale(0.0)";
            style += "}</style>  <br> "
                
                var promise = $scope.getCoveredServices();
                $scope.loadingForPrint = true;                
                promise.then(function ()
                {
                    var promise2 = $scope.getBenefitSummaryWaitingPeriods();
                    promise2.then(function ()
                    {                                 
                        var promise3 =  $scope.getServiceLimitationsData();
                    
                        promise3.then(function ()
                        {        
                       
                         $timeout(function ()
                            {                 
                            var benefitSummaryReportPrintContents="";
                            var mmemberInfo= document.getElementById('BenefitSummaryPanelHeading').innerHTML;
                            var memberHeaderData = document.getElementById('memberHeaderInformation').innerHTML;
                            var generalInfoData = document.getElementById('generalInformationResultsInNetwork').innerHTML;
                            var generalInfoDataOON = document.getElementById('generalInformationResultsOutOfNetwork').innerHTML;
                            var serviceLimitationsData = document.getElementById('serviceLimitationsResults').innerHTML;
                            var serviceLimitationsCodesetsData = document.getElementById('serviceLimitationsCodesetsResults').innerHTML;
                            var waitingPeriodData = document.getElementById('waitingPeriodResults').innerHTML;
                            var coveredServicesData = document.getElementById('coveredServicesResults').innerHTML;
                            
                            benefitSummaryReportPrintContents = style; 
                            benefitSummaryReportPrintContents += mmemberInfo;   
                            benefitSummaryReportPrintContents += memberHeaderData;
                            benefitSummaryReportPrintContents += generalInfoData;
                            benefitSummaryReportPrintContents += generalInfoDataOON;
                            benefitSummaryReportPrintContents += serviceLimitationsData;
                            benefitSummaryReportPrintContents += serviceLimitationsCodesetsData;
                            benefitSummaryReportPrintContents += waitingPeriodData;
                            benefitSummaryReportPrintContents += coveredServicesData;
                                 
                            printOutput = $sce.trustAsHtml(benefitSummaryReportPrintContents);
                               
                                var printWindow = window.open('','','width=900, height=500');
                                    printWindow.document.write(printOutput);
                                    printWindow.print();
                                    printWindow.document.close();
                                    printWindow.focus();     
                                    $scope.loadingForPrint = false;                                   
                           }, 3000);                             
                        });
                    });              
                });          
            }

            $scope.getMemberHeaderDataForPrint = function(){
                var memberHeaderData = "<div class='resultsContainer'>"
                       memberHeaderData += "<table>"
                        memberHeaderData += "<tr><td>Insurer:</td><td>" + $scope.benefitSummaryMemberHeaderData.INSURER_NAME + "</td></tr>"
                        memberHeaderData += "<tr><td>Member ID:</td><td>" + $scope.benefitSummaryMemberHeaderData.MEMBER_ID + "</td></tr>"
                        memberHeaderData += "<tr><td>Benefit Plan Eligibility:</td><td>" + $scope.benefitSummaryMemberHeaderData.ELIGIBILITY_STATUS.STATUS_DESCRIPTION + "</td></tr>"
                        memberHeaderData += "<tr><td>Benefit Plan:</td><td>" + $scope.benefitSummaryMemberHeaderData.BENEFIT_PLAN_NAME + "</td></tr>"
                        memberHeaderData += "<tr><td>Plan/Group Number:</td><td>" + $scope.benefitSummaryMemberHeaderData.GROUP_NUMBER +"</td></tr>"
                        memberHeaderData += "<tr><td>Benefit Plan Period:</td><td>" + $scope.benefitSummaryMemberHeaderData.BENEFIT_PLAN_PERIOD + "</td></tr>"
                        memberHeaderData += "</table>"
           
                        return memberHeaderData;
            }

            $scope.getServiceLimitationCodesetsForPrint = function(){
                var limitationByCodesets = document.getElementById('generalInfoResultsTable').innerHTML;
                return limitationByCodesets;
            }
            

            

            $scope.procedureCodeSearch = function(productCode){
                var sessionProperties = $scope.setSessionPropertiesForPortalBenefitSummaryReport();               
                $scope.codeSearchResult =[] ;  
                $scope.invalidCode = false; 
                $scope.hasSearchResults = false;  
                $scope.hasCodesets=false;    
                $scope.codeSearchForm.$submitted=true; 
                    
                if ($scope.codeSearchForm.$invalid || productCode.length < 5 )
                    {
                    $scope.searchCode = '';
                    return false;
                }

                $http({
                    method: 'GET',
                    url: '/PWP/BenefitSummaryReport/BenefitSummaryCodeSearch',
                    params: {
                        productId: parseInt(sessionProperties[1].SESSION_VALUE),
                        benefitLevel:  null,
                        enrolleeId: $scope.selectedItem.ENROLLEE_ID,
                        dateOfService: sessionProperties[0].SESSION_VALUE,
                        code: productCode             
                    }
                }).then(function (data) {
                    $scope.codeSearchResult = data.data;
                      $scope.hasSearchResults = $scope.codeSearchResult.length >0 ;  
                    $scope.hasCodesets = false;
                    var hasCodeset = $scope.codeSearchResult.map(function (item, index) {
                    if(item.CODESET_DESCRIPTION.length >0 )
                    {
                        $scope.hasCodesets=true;
                    }
                    if(item.DESCRIPTION =='- Invalid Code -'){
                    $scope.invalidCode = true;
                    }
                });                     
               });         
            }
    
               $scope.clearCodeSearchResults = function(){
                $scope.searchCode = '';
                $scope.codeSearchForm.$invalid = false;
                $scope.codeSearchForm.$submitted = false;  
                $scope.codeSearchResult = [];
                $scope.hasCodesets = false;      
                $scope.hasSearchResults = false;   
            }

           $("#procedureCodeSearch").keydown(function (event)
                {
                if(event.which == 13){
                     $scope.procedureCodeSearch($scope.searchCode);
                }
            });
                
           

            $scope.changeIconOnClick = function (data) { 
            data.collapsed  = !data.collapsed;
                $('#' + this.id).on('shown.bs.collapse',
                    function () {
                       $(this).parent().find('.panel-heading').addClass('panel-heading-opened');
                        $(this).parent().find(".fa-caret-right").removeClass("fa-caret-right")
                            .addClass("fa-caret-up");
                    }).on('hidden.bs.collapse',
                    function () {
                        $(this).parent().find('.panel-heading').removeClass('panel-heading-opened');
                        $(this).parent().find(".fa-caret-up").removeClass("fa-caret-up").addClass("fa-caret-right");
                    });    
                }

            $scope.formatBenefitMaximumData = function(data){          
                var output = '';
                if(data.ANNUAL_IND_MAX_LIMIT === 0){
                  output =  'N/A/'
                }
                else{
                    output = data.ANNUAL_IND_MAX_USED + ' used of' + data.ANNUAL_IND_MAX_LIMIT
                }

                if(data.ANNUAL_IND_MAX_LIMIT - data.ANNUAL_IND_MAX_USED === 0){
                  output =  ''
                }
                else{
                    output = (ANNUAL_IND_MAX_LIMIT - ANNUAL_IND_MAX_USED) + ' remains'
                }
                return output;
            }

           

            $scope.multiProductShowPortalBenefitSummaryReport = function (productInfo) {
                $scope.selectedItem.PRODUCT_ID = productInfo.PRODUCT_ID;
                $scope.showPortalBenefitSummaryReport();
            }

            $scope.showPatientHistory = function () {

                googleTagManagerService.setClickInfo('click', 'verify member eligibility / start claim or authorization', 'patient selected - view patient history button', 'field_interaction', '', 'button', 'view patient history');

                var googletaginfo = {
                    "attribute1": 'verify member eligibility / start claim or authorization',
                    "attribute2": 'patient selected - view patient history button',
                    "attribute3": 'field_interaction',
                    "attribute4": 'patient history generated successfully',
                    "category": 'button',
                    "label": 'view patient history',
                }

                if ($scope.selectedItem.ENROLLEE_ID != null && $scope.selectedItem.SUBSCRIBER_ID.length > 0) {
                    var sessionProperties = [];
                    var sessionProperty = {
                        SESSION_NAME: "REPORT_SERVICE_HISTORY_ENROLLEE_ID",
                        SESSION_VALUE: $scope.selectedItem.ENROLLEE_ID
                    }
                    sessionProperties.push(sessionProperty);

                    var sessionProperty = {
                        SESSION_NAME: "REPORT_SERVICE_HISTORY_SUBSCRIBER_ID",
                        SESSION_VALUE: $scope.selectedItem.SUBSCRIBER_ID
                    }
                    sessionProperties.push(sessionProperty);

                    $scope.openTab("/Areas/PWP/Reports/ServiceHistory.aspx", sessionProperties, googletaginfo);
                }
            }

            $scope.multiProdutShowPatientHistory = function (productInfo) {
                $scope.selectedItem.ENROLLEE_ID = productInfo.ENROLLEE_ID;
                $scope.selectedItem.SUBSCRIBER_ID = productInfo.SUBSCRIBER_ID;
                $scope.selectedItem.STATUS = productInfo.STATUS;
                $scope.showPatientHistory();
            }

            $scope.addToRoster = function (patient, googletaginfo) {

                googletaginfo = googletaginfo || "notag";

                var deferred = $q.defer();
                $http({
                    url: "/PatientManagement/AddMembers",
                    method: "PUT",
                    data: {
                        ROSTER_ID: null,
                        LOCATION_ID: patient.LOCATION_ID,
                        IS_LOCATION_ROSTER: true,
                        EnrolleeIds: patient.ENROLLEE_ID
                    }
                }).then(function successCallback(response) {

                    if (googletaginfo != "notag") {
                        googleTagManagerService.setClickInfo('success', googletaginfo.attribute1, googletaginfo.attribute2, googletaginfo.attribute3, googletaginfo.attribute4, googletaginfo.category, googletaginfo.label);
                    }

                    $scope.isAddedToRoster = (response.data.INSERTED_ROW_COUNT == 1);
                    deferred.resolve(true); 

                }, function errorCallback(response) {

                    console.error(response.data.Message);
                    console.error(response);
                    if ($scope.ExceptionDialogControl != null) {

                        if (googletaginfo != "notag") {
                            googleTagManagerService.setClickInfo('error', googletaginfo.attribute1, googletaginfo.attribute2, googletaginfo.attribute3, 'error with adding member to roster', googletaginfo.category, googletaginfo.label);
                        }

                        $scope.ExceptionDialogControl.showDialog("Error with adding member to roster.");
                    }
                    else {
 
                        if (googletaginfo != "notag") {

                            googleTagManagerService.setClickInfo('error', googletaginfo.attribute1, googletaginfo.attribute2, googletaginfo.attribute3, ((response.data.Message) ? response.data.Message.toLowerCase() : "an error has occurred"), googletaginfo.category, googletaginfo.label);
                        }

                        bootbox.alert(response.data.Message);
                    }                    
                });
                return deferred.promise;
            }

            $scope.addToCalendar = function (patient) {
                $http({
                    url: "/PatientManagement/AddCalendarMembers/",
                    method: "PUT",
                    data: {
                        LOCATION_ID: patient.LOCATION_ID,
                        PROVIDER_ID: patient.PROVIDER_ID,
                        DATE_OF_SERVICE: patient.DATE_OF_SERVICE,
                        EnrolleeIds: patient.ENROLLEE_ID
                    }
                }).then(function successCallback(response) {
                    $scope.isAddedToCalendar = (response.data == 1);
                }, function errorCallback(response) {
                    console.error(response.data.Message);
                    console.error(response);
                    if ($scope.ExceptionDialogControl != null) {
                        $scope.ExceptionDialogControl.showDialog("Error with adding member to calendar.");
                    }
                    else {
                        bootbox.alert(response.data.Message);
                    }
                });
            }

               
            $scope.addToPatientManagement = function (patient, product) {

                googleTagManagerService.setClickInfo('click', 'verify member eligibility / start claim or authorization', 'patient selected - add to patient management button', 'field_interaction', '', 'button', 'add to patient management');

                var googletaginfo = {
                    "attribute1": 'verify member eligibility / start claim or authorization',
                    "attribute2": 'patient selected - add to patient management button',
                    "attribute3": 'field_interaction',
                    "attribute4": 'added to patient management successfully',
                    "category": 'button',
                    "label": 'add to patient management',
                }

                if (product != null) {
                    patient.INSURER_ID = product.INSURER_ID;
                    patient.INSURER_NAME = product.INSURER_NAME;
                    patient.MEMBER_ID = product.MEMBER_ID;
                    patient.PRODUCT_ID = product.PRODUCT_ID;
                    patient.PRODUCT_NAME = product.PRODUCT_NAME;
                    patient.ENROLLEE_ID = product.ENROLLEE_ID;
                }

                var promise = $scope.addToRoster(patient, googletaginfo);
                promise.then(function ()
                    {                               
                        $scope.addToCalendar(patient);
                    });                   
                //If this is called by Member on the fly, don't close the dialog after adding it to patient management.
                // We do show the banner in the dialog
                if ($scope.pageSource != 7) {
                    $('#MemberAction' + $scope.MemberActionId + 'Dialog').modal('hide');
                }
            }

            $scope.setSessionProperties = function (sessionProperties, googletaginfo) {
                var deferred = $q.defer();

                $http({
                    url: "/PortalWebSession/SetWebSessionProperties",
                    method: "PUT",
                    data: {
                        SESSION_PROPERTIES: sessionProperties
                    }
                }).then(function successCallback(response) {
                    if (!response.data.Status) {
                        console.error(response.data.Message);
                        console.error(response);
                        if ($scope.ExceptionDialogControl != null) {

                            if (googletaginfo != "notag") {
                                googleTagManagerService.setClickInfo('error', googletaginfo.attribute1, googletaginfo.attribute2, googletaginfo.attribute3, 'error with setting web session properties', googletaginfo.category, googletaginfo.label);
                            }

                            $scope.ExceptionDialogControl.showDialog("Error with setting web session properties.");
                        }
                        else {

                            if (googletaginfo != "notag") {

                                googleTagManagerService.setClickInfo('error', googletaginfo.attribute1, googletaginfo.attribute2, googletaginfo.attribute3, ((response.data.Message) ? response.data.Message.toLowerCase() : "an error has occurred"), googletaginfo.category, googletaginfo.label);
                            }

                            bootbox.alert(response.data.Message);
                        }
                        deferred.reject(false);
                    }
                    else {

                        if (googletaginfo != "notag") {
                            googleTagManagerService.setClickInfo('success', googletaginfo.attribute1, googletaginfo.attribute2, googletaginfo.attribute3, googletaginfo.attribute4, googletaginfo.category, googletaginfo.label);
                        }

                        deferred.resolve(true);
                    }
                }, function errorCallback(response) {
                    console.error(response.data.Message);
                    console.error(response);
                    if ($scope.ExceptionDialogControl != null) {

                        if (googletaginfo != "notag") {
                            googleTagManagerService.setClickInfo('error', googletaginfo.attribute1, googletaginfo.attribute2, googletaginfo.attribute3, 'error with setting web session properties', googletaginfo.category, googletaginfo.label);
                        }

                        $scope.ExceptionDialogControl.showDialog("Error with setting web session properties.");
                    }
                    else {

                        if (googletaginfo != "notag") {

                            googleTagManagerService.setClickInfo('error', googletaginfo.attribute1, googletaginfo.attribute2, googletaginfo.attribute3, ((response.data.Message) ? response.data.Message.toLowerCase() : "an error has occurred"), googletaginfo.category, googletaginfo.label);
                        }

                        bootbox.alert(response.data.Message);
                    }
                    deferred.reject(false);
                });

                return deferred.promise;
            }

            $scope.openTab = function (url, sessionProperties, googletaginfo) {
                var randomno = Math.floor((Math.random() * 100) + 1);
                var newWindow = $window.open('', 'PopUpWindow' + randomno, 'scrollbars=1,menubar=0,resizable=1,width=920,height=850');

                googletaginfo = googletaginfo || "notag";

                var promise = $scope.setSessionProperties(sessionProperties, googletaginfo);
                promise.then(function () {
                    newWindow.location = url;
                }, function (data) {
                    // bad, do nothing
                });
            }

            $scope.evaluateStartClaimButtonForTherapy = function () {
                var dateOfService = moment($scope.selectedItem.DATE_OF_SERVICE, "MM/DD/YYYY").startOf('day');
                var today = moment().startOf('day');
                $scope.IsFutureDate = (dateOfService > today);
            }

            $scope.showSelectedItemInfo = function () {
                console.log($scope.selectedItem);
            }
        }],
        link: function (scope, element, attr) {
            scope.MemberActionId = attr.name != null ? attr.name.replace(/ /g, "").replace(/-/g, "") : "";
            scope.init();
        }
    };
}]);

app.directive('wbxEligibilityResults', ['$timeout', '$http', function ($timeout, $http)
{
    return {
        restrict: 'E',
        templateUrl: '/Templates/EligibilityResults',
        scope: {
            eligibilityResults: '=',
            dateOfService: '=',
            locationId: '=',
            locationName: '=',
            providerId: '=',
            providerName: '=',
            isVision: '=?',
            isTherapy: '=?',
            showMemberOnTheFlyRow: '=?',
            requestToCreateMember: '=?',
            requestToCreatePrimary: '=?',
            resultSelect: '&'
        },
        controller: ['$scope', 'FeatureFlagService', function ($scope, featureFlagService)
        {
            $scope.init = function () {
                if ($scope.isVision){
                    featureFlagService.getFeatureFlagsForPWPVisionMedicaid()
                    .then(function (response) {
                        $scope.isPWPVisionMedicaidEnabled = response.IsVisionMedicaidEnabled;
                    });
                }
            }

            $scope.$watchCollection('eligibilityResults', function (n, o)
            {
                if (!(n === o) && n != null)
                {
                    if ($scope.isVision)
                    {
                        $scope.evaluateDateOfService();
                    }

                    if (!$scope.isVision && !$scope.isTherapy && $scope.eligibilityResults.length == 1)
                    {
                        //If it's vision, we don't want to click on select button immediately even though
                        // it's only one record since vision doesn't have a pop up action dialog.
                        // Vision goes to claim entry directly.
                        $scope.ResultSelect($scope.eligibilityResults[0]);
                    }

                    $timeout(function ()
                    {
                        $('html, body').animate({
                            scrollTop: $('#search-results').offset().top
                        }, 750);
                    }, 250);
                }
            });

            $scope.ResultSelect = function (result, isHoldMode, isClaim, pricingRequestId)
            {

                $scope.selectedResult = angular.copy(result);
                $scope.selectedResult.DATE_OF_SERVICE = $scope.dateOfService;
                $scope.selectedResult.LOCATION_ID = $scope.locationId;
                $scope.selectedResult.LOCATION_NAME = $scope.locationName;
                $scope.selectedResult.PROVIDER_ID = $scope.providerId;
                $scope.selectedResult.PROVIDER_NAME = $scope.providerName;
                $scope.selectedResult.isClaim = isClaim;
                if($scope.selectedResult.isClaim)
                {
                    $scope.selectedResult.IS_AUTHORIZATION_FLAG = false
                }
                else{
                    $scope.selectedResult.IS_AUTHORIZATION_FLAG = true
                }

                $scope.selectedResult.STATUS = result.STATUS;
                if (result.PRODUCTS != null && result.PRODUCTS.length > 1)
                {
                    $scope.productLevelResults = result.PRODUCTS;
                }
                else
                {
                    $scope.selectedResult.INSURER_ID = result.INSURER_ID;
                    $scope.selectedResult.INSURER_NAME = result.INSURER_NAME;
                    $scope.selectedResult.MEMBER_ID = result.MEMBER_ID;
                    $scope.selectedResult.PRODUCT_ID = result.PRODUCT_ID;
                    $scope.selectedResult.PRODUCT_NAME = result.PRODUCT_NAME;
                    $scope.productLevelResults = null;
                }
                if (!$scope.isVision)
                {
                    $scope.resultSelect({ selectedResult: $scope.selectedResult, productLevelResults: $scope.productLevelResults, visionInfo: null });
                }
                else
                {
                    
                    $scope.visionInfo.IS_HOLD_MODE = isHoldMode;
                    if((!$scope.selectedResult.isClaim && $scope.selectedResult.IS_AUTHORIZATION_FLAG) || ($scope.selectedResult.isClaim && !$scope.selectedResult.IS_AUTHORIZATION_FLAG))
                    { 
                    $scope.visionInfo.PRICING_REQUEST_ID = pricingRequestId;
                    }            
                    $scope.visionInfo.IS_EDIT_MODE = ($scope.isPastDateOfService || $scope.isPresentDateOfService) && !$scope.visionInfo.IS_HOLD_MODE;                    
                    $scope.visionInfo.IS_CLAIM = isClaim;
                    
                    if (result.PRICING_REQUEST_DATE != null && !$scope.visionInfo.IS_HOLD_MODE && $scope.selectedResult.isClaim)
                    {
                        var pricingRequestDate = moment(result.PRICING_REQUEST_DATE, "MM/DD/YYYY").startOf('day');
                        var dateOfService = moment($scope.dateOfService, "MM/DD/YYYY").startOf('day');

                        if (dateOfService.toString() != pricingRequestDate.toString())
                        {
                            $('#VisionExistingPricingRequestDialog').modal({
                                backdrop: 'static'
                            })
                            $('#VisionExistingPricingRequestDialog').modal('show');
                            return;
                        }
                    }
                    else {
                        $scope.visionInfo.IsResume = false;
                    }

                    $scope.visionResultSelect();
                }
            }

            //Specific to vision - start
            $scope.visionInfo = {};

             $scope.visionResultSelect = function ()
            {
                $scope.ShowStartPricingRequestProcess = true;
               
                $scope.resultSelect({ selectedResult: $scope.selectedResult, productLevelResults: $scope.productLevelResults, visionInfo: $scope.visionInfo });
            }

            $scope.evaluateDateOfService = function ()
            {
                var dateOfService = moment($scope.dateOfService, "MM/DD/YYYY").startOf('day');
                var today = moment().startOf('day');
                $scope.isPastDateOfService = today > dateOfService;
                $scope.isPresentDateOfService = today.toString() == dateOfService.toString();
                $scope.isFutureDateOfService = today < dateOfService;
            }

            $scope.cancelExistingPricingRequestDialog = function ()
            {
                $('#VisionExistingPricingRequestDialog').modal('hide');
            }

            $scope.resumePricingRequest = function ()
            {
                $scope.selectedResult.DATE_OF_SERVICE = $scope.selectedResult.PRICING_REQUEST_DATE;
                $scope.visionInfo.IsResume = true;
                $scope.visionInfo.IS_EDIT_MODE = true;
                $scope.visionResultSelect();
            }

            $scope.newPricingRequest = function ()
            {
                $scope.visionInfo.IsResume = false;
                $scope.ShowStartPricingRequestProcess = true;
                $http({
                    url: "/Vision/DeletePricingRequests",
                    method: "PUT",
                    data: {
                        ENROLLEE_ID: $scope.selectedResult.ENROLLEE_ID,
                        LOCATION_ID: $scope.selectedResult.LOCATION_ID,
                        PROVIDER_ID: $scope.selectedResult.PROVIDER_ID
                    }
                }).then(function successCallback(response) {
                    if (!response.data.Status) {
                        console.error(response.data.Message);
                        console.error(response);
                        if ($scope.ExceptionDialogControl != null) {
                            $scope.ExceptionDialogControl.showDialog("Error with deleting pricing requests.");
                        }
                        else {
                            bootbox.alert(response.data.Message);
                        }
                    }
                    else {
                        $scope.visionInfo.PRICING_REQUEST_ID = null;
                        $scope.selectedResult.DATE_OF_SERVICE = $scope.dateOfService;
                        $scope.visionResultSelect();
                    }
                }, function errorCallback(response) {
                    console.error(response.data.Message);
                    console.error(response);
                    if ($scope.ExceptionDialogControl != null) {
                        $scope.ExceptionDialogControl.showDialog("Error with deleting pricing requests.");
                    }
                    else {
                        bootbox.alert(response.data.Message);
                    }
                });

            }
            //Specific to vision - end

            //Specific to therapy - start
            $scope.createMember = function () {
                $scope.requestToCreateMember = true;
            }

            //Specific to therapy - end

        }]
    };
}]);

app.directive('wbxCalendar', ['$filter', '$http', '$timeout', '$q', '$window', function ($filter, $http, $timeout, $q, $window) {
    return {
        restrict: 'E',
        templateUrl: '/Templates/Calendar',
        scope: {
            currentDay: '=',
            calendarEvents: '=',
            inputInfo: '=',
            calendarActionInfo: '=',
            displayMemberAction: '=',
            displayMemberLevelResults: '=',
            selectedItem: '=',
            memberLevelResults: '=',
            productLevelResults: '=',
            isDragAndDropOn: '=',
            calendarControl: '=',
            addToCalendarDate: '=',
            isTherapy: '='
        },
        controller: ['$scope', function ($scope) {
            $scope.timer = null;
            $scope.view = 'month';
            $scope.openDay = {};
            //helper

            $scope.isISOWeek = function () {
                return moment().startOf('week').day() === 1;
            };

          

            $scope.eventIsInPeriod = function (dateOfService, date) {
                return moment(dateOfService, "MM/DD/YYYY").isSame(moment(date, "MM/DD/YYYY"));
            };

            $scope.getWeekDayNames = function (short) {
                var format = short ? 'EEE' : 'EEEE';

                var weekdays = [];
                var startDay = $scope.isISOWeek() ? 22 : 21;
                for (var i = 0; i <= 6; i++) {
                    weekdays.push($filter('date')(new Date(2014, 8, startDay + i), format));
                }
                return weekdays;

            };

            $scope.getMonthView = function (events, currentDay, useISOWeek) {

                var dateOffset = $scope.isISOWeek() ? 1 : 0;

                function getWeekDayIndex() {
                    var day = startOfMonth.day() - dateOffset;
                    if (day < 0) day = 6;
                    return day;
                }

                var startOfMonth = moment(new Date(currentDay)).startOf('month');
                var numberOfDaysInMonth = moment(new Date(currentDay)).endOf('month').date();

                var grid = [];
                var buildRow = new Array(7);
                var eventsWithIds = events.map(function (event, index) {
                    event.$id = index;
                    return event;
                });
                for (var i = 1; i <= numberOfDaysInMonth; i++) {

                    if (i == 1) {
                        var weekdayIndex = getWeekDayIndex(startOfMonth);
                        var prefillMonth = startOfMonth.clone();
                        while (weekdayIndex > 0) {
                            weekdayIndex--;
                            prefillMonth = prefillMonth.subtract(1, 'day');
                            buildRow[weekdayIndex] = {
                                label: prefillMonth.date(),
                                date: prefillMonth.clone(),
                                inMonth: false,
                                events: []
                            };
                        }
                    }

                    buildRow[getWeekDayIndex(startOfMonth)] = {
                        label: startOfMonth.date(),
                        inMonth: true,
                        isToday: moment().startOf('day').isSame(startOfMonth),
                        date: startOfMonth.clone(),
                        events: eventsWithIds.filter(function (event) {
                            return $scope.eventIsInPeriod(event.DATE_OF_SERVICE, startOfMonth.clone().startOf('day'));
                        })
                    };

                    if (i == numberOfDaysInMonth) {
                        var weekdayIndex = getWeekDayIndex(startOfMonth);
                        var postfillMonth = startOfMonth.clone();
                        while (weekdayIndex < 6) {
                            weekdayIndex++;
                            postfillMonth = postfillMonth.add(1, 'day');
                            buildRow[weekdayIndex] = {
                                label: postfillMonth.date(),
                                date: postfillMonth.clone(),
                                inMonth: false,
                                events: []
                            };
                        }
                    }

                    if (getWeekDayIndex(startOfMonth) === 6 || i == numberOfDaysInMonth) {
                        grid.push(buildRow);
                        buildRow = new Array(7);
                    }

                    startOfMonth = startOfMonth.add(1, 'day');

                }
                return grid;
            };

            $scope.toggleEventBreakdown = function (view, rowIndex, cellIndex) {
       

                var openEvents = [];
                var isCellOpened = view[rowIndex][cellIndex].isOpened;
                var selectedRowIndex = null;
                var selectedCellIndex = null;
                view = view.map(function (row) {
                    row.isOpened = false;
                    return row.map(function (cell) {
                        cell.isOpened = false;
                        return cell;
                    });
                });

                if (view[rowIndex][cellIndex].events.length > 0) {
                    view[rowIndex][cellIndex].isOpened = !isCellOpened;
                    view[rowIndex].isOpened = !isCellOpened;
                    if (view[rowIndex][cellIndex].isOpened) {
                        openEvents = view[rowIndex][cellIndex].events;
                        selectedRowIndex = rowIndex;
                        selectedCellIndex = cellIndex;
                    }
                    else {
                        openEvents = [];
                        selectedRowIndex = null;
                        selectedCellIndex = null;
                    }
                }
                return { view: view, openEvents: openEvents, selectedRowIndex: selectedRowIndex, selectedCellIndex: selectedCellIndex };

            };

            $scope.setNoProviderFlag = function () {
                //If provider dropdown list is set to all providers, we can't add to the calendar.
                $scope.calendarActionInfo.noProvider = true;
                //Close the info banner automatically in 3 seconds
                //$timeout.cancel($scope.timer);
                //$scope.timer = $timeout(function () {
                //    $scope.calendarActionInfo.noProvider = false;
                //}, 3000);
            }

            $scope.showMemberAction = function (selectedItem, productLevelResults) {
                $scope.displayMemberAction = true;
                $scope.selectedItem = selectedItem;
                $scope.productLevelResults = productLevelResults;

                $timeout.cancel($scope.timer);
                $scope.timer = $timeout(function () {
                    $scope.displayMemberAction = false;
                }, 1000);
            }

            $scope.showMemberLevelResults = function (memberLevelResults, DATE_OF_SERVICE) {
                $scope.memberLevelResults = memberLevelResults;
                $scope.memberLevelResults.DATE_OF_SERVICE = DATE_OF_SERVICE;
                $scope.displayMemberLevelResults = true;

                $timeout.cancel($scope.timer);
                $scope.timer = $timeout(function () {
                    $scope.displayMemberLevelResults = false;
                }, 1000);
            }

            $scope.updateView = function () {
                if ($scope.calendarEvents != null) {
                    $scope.calendarView = $scope.getMonthView($scope.calendarEvents, $scope.currentDay, $scope.useIsoWeek);
                    
                    //if (!$scope.hasTodayOpened) {
                        //$scope.calendarView.forEach(function (week, rowIndex) {
                        //    week.forEach(function (day, cellIndex) {
                        //        if (day.inMonth && moment($scope.currentDay).startOf('day').isSame(day.date.startOf('day'))) {
                        //            //console.log("updateView");
                        //            $scope.dayClicked(rowIndex, cellIndex);
                        //            //$scope.hasTodayOpened = true;
                        //        }
                        //    });
                        //});
                    //}
                }
            }

            $scope.updateDayView = function () {
                if ($scope.openDay.rowIndex != null && $scope.openDay.cellIndex != null &&
                    (($scope.openDay.rowIndex != $scope.selectedRowIndex) ||
                     ($scope.openDay.cellIndex != $scope.selectedCellIndex))) {
                    $scope.dayClicked($scope.openDay.rowIndex, $scope.openDay.cellIndex);
                }
            }

            $scope.$watchCollection('[openDay.rowIndex, openDay.cellIndex]', $scope.updateDayView);
            //$scope.$watch('currentDay', $scope.updateDayView);
            $scope.$watch('calendarEvents', $scope.updateView);

            $scope.weekDays = $scope.getWeekDayNames(true);

            $scope.dayClicked = function (rowIndex, cellIndex) {
                var handler = $scope.toggleEventBreakdown($scope.calendarView, rowIndex, cellIndex);
                $scope.calendarView = handler.view;
                $scope.openEvents = handler.openEvents;

                $scope.openEvents.calendarMemberSearchText = '';
                $scope.openEvents.sortColumn = 'LAST_NAME';
                $scope.openEvents.reverse = false;

                $scope.selectedRowIndex = handler.selectedRowIndex;
                $scope.selectedCellIndex = handler.selectedCellIndex;

                $scope.currentDay = $filter('date')($scope.calendarView[rowIndex][cellIndex].date._d, 'MM/dd/yyyy');
                $scope.addToCalendarDate = $scope.currentDay;
            };

            //end helper
            $scope.calendarControl.dropCallBack = function (item, targetDate, updateView) {
                var targetRowIndex = null;
                var targetCellIndex = null;

                if (updateView) {
                    $scope.calendarView = $scope.getMonthView($scope.calendarEvents, $scope.currentDay, $scope.useIsoWeek);
                }

                angular.forEach($scope.calendarView, function (week, rowIndex) {
                    angular.forEach(week, function (day, cellIndex) {
                        if (day.inMonth && moment(new Date(targetDate)).startOf('day').isSame(day.date.startOf('day'))) {
                            targetRowIndex = rowIndex;
                            targetCellIndex = cellIndex;
                        }
                    });
                });

                $scope.calendarDropCallback(item, targetRowIndex, targetCellIndex);
            }

            //DropDown
            $scope.calendarDropCallback = function (item, rowIndex, cellIndex) {
                if (item.DATE_OF_SERVICE == $filter('date')($scope.calendarView[rowIndex][cellIndex].date._d, 'MM/dd/yyyy')) {
                    //Won't allow dropping in the same bucket.
                    return false;
                }
                else if ($scope.inputInfo.PROVIDER_ID == -1) {
                    //Provider drop down isn't selected
                    $scope.setNoProviderFlag();
                    return false;
                }

                var itemAlreadyAdded = false;
                var potentialOpenEvents = $scope.calendarView[rowIndex][cellIndex].events;
                
                if (potentialOpenEvents.length > 0) {
                    angular.forEach(potentialOpenEvents, function (value, key) {
                        if (value.LAST_NAME == item.LAST_NAME &&
                            value.FIRST_NAME == item.FIRST_NAME &&
                            value.DOB == item.DOB) {
                            itemAlreadyAdded = true;
                        }
                    });
                }

                if (!itemAlreadyAdded) {
                    item.bucketIndex = null;
                    $scope.addCalendarMembers(item, rowIndex, cellIndex);
                }
                else {
                    $scope.actionStatus(null, 0, 1, rowIndex, cellIndex);
                }

                return false;
            };

            $scope.calendarEventsDropCallback = function (item) {
                if (item.DATE_OF_SERVICE == $filter('date')($scope.calendarView[$scope.selectedRowIndex][$scope.selectedCellIndex].date._d, 'MM/dd/yyyy')) {
                    //Won't allow dropping in the same bucket.
                    return false;
                }
                else if ($scope.inputInfo.PROVIDER_ID == -1) {
                    $scope.setNoProviderFlag();
                    return false;
                }

                if ($scope.selectedRowIndex == null || $scope.selectedCellIndex == null) {
                    return false;
                }

                var itemAlreadyAdded = false;
                $scope.openEvents = $scope.calendarView[$scope.selectedRowIndex][$scope.selectedCellIndex].events;

                if ($scope.openEvents.length > 0) {
                    angular.forEach($scope.openEvents, function (value, key) {
                        if (value.LAST_NAME == item.LAST_NAME &&
                            value.FIRST_NAME == item.FIRST_NAME &&
                            value.DOB == item.DOB) {
                            itemAlreadyAdded = true;
                        }
                    });
                }
                if (!itemAlreadyAdded) {
                    item.bucketIndex = null;
                    $scope.addCalendarMembers(item, $scope.selectedRowIndex, $scope.selectedCellIndex);
                }
                else {
                    $scope.actionStatus(null, 0, 1, $scope.selectedRowIndex, $scope.selectedCellIndex);
                }
                return false;
            };

            $scope.addCalendarMembers = function (item, rowIndex, cellIndex) {
                var addedMembersList = [];
                item.LOCATION_ID = $scope.inputInfo.LOCATION_ID;
                item.LOCATION_NAME = $scope.inputInfo.selectedLocation.NAME;

                item.PROVIDER_ID = $scope.inputInfo.PROVIDER_ID;
                item.PROVIDER_NAME = $scope.inputInfo.selectedProvider.NAME;

                item.DATE_OF_SERVICE = $filter('date')($scope.calendarView[rowIndex][cellIndex].date._d, 'MM/dd/yyyy');
                addedMembersList.push(item);

                //Construct a string of enrollee Ids.
                var enrolleeIds = '';
                angular.forEach(addedMembersList, function (value, key) {
                    if (enrolleeIds != "")
                        enrolleeIds += "|"
                    enrolleeIds += value.ENROLLEE_ID;
                });

                $http({
                    url: "/PatientManagement/AddCalendarMembers/",
                    method: "PUT",
                    data: {
                        LOCATION_ID: $scope.inputInfo.LOCATION_ID,
                        PROVIDER_ID: $scope.inputInfo.PROVIDER_ID,
                        DATE_OF_SERVICE: item.DATE_OF_SERVICE,
                        EnrolleeIds: enrolleeIds
                    }
                }).then(function successCallback(response) {
                    $scope.actionStatus(addedMembersList, response.data, 1 - response.data, rowIndex, cellIndex);
                }, function errorCallback(response) {
                    console.error(response.data.Message);
                    console.error(response);
                    if ($scope.ExceptionDialogControl != null) {
                        $scope.ExceptionDialogControl.showDialog("Error with adding member to calendar.");
                    }
                    else {
                        bootbox.alert(response.data.Message);
                    }
                });
            }

            $scope.actionStatus = function (addedMembersList, addedCount, existCount, rowIndex, cellIndex) {
                $scope.calendarActionInfo.addedCount = addedCount;
                $scope.calendarActionInfo.existCount = existCount;
                $scope.calendarActionInfo.addedDate = $filter('date')($scope.calendarView[rowIndex][cellIndex].date._d, 'MM/dd/yyyy');

                if (addedCount > 0 && addedMembersList != null && addedMembersList.length > 0) {
                    $scope.openDay = { rowIndex: rowIndex, cellIndex: cellIndex };
                    angular.forEach(addedMembersList, function (addedMember, key) {
                        $scope.calendarView[rowIndex][cellIndex].events.push(addedMember);
                    });
                }

                $timeout.cancel($scope.timer);
                //Close the info banner automatically in 3 seconds
                $scope.timer = $timeout(function () {
                    $scope.calendarActionInfo.addedCount = 0;
                    $scope.calendarActionInfo.existCount = 0;
                    $scope.calendarActionInfo.addedDate = null;
                }, 3000);

            }

            $scope.deleteCalendarMembers = function (patient) {
if (!$scope.$parent.isImpersonation)
{
                $http({
                    url: "/PatientManagement/DeleteCalendarMembers",
                    method: "PUT",
                    data: {
                        LOCATION_ID: patient.LOCATION_ID,
                        PROVIDER_ID: patient.PROVIDER_ID,
                        DATE_OF_SERVICE: patient.DATE_OF_SERVICE,
                        EnrolleeIds: patient.ENROLLEE_ID
                    }
                }).then(function successCallback(response) {
                    var index = $scope.openEvents.indexOf(patient);
                    $scope.openEvents.splice(index, 1);
                    if ($scope.openEvents.length <= 0) {
                        $scope.dayClicked($scope.selectedRowIndex, $scope.selectedCellIndex);
                    }
                }, function errorCallback(response) {
                    console.error(response.data.Message);
                    console.error(response);
                    if ($scope.ExceptionDialogControl != null) {
                        $scope.ExceptionDialogControl.showDialog("Error with deleting member from calendar.");
                    }
                    else {
                        bootbox.alert(response.data.Message);
                    }
                });
}
            }

            $scope.sort = function (columnName) {
                if ($scope.openEvents.sortColumn != columnName)
                    $scope.openEvents.reverse = false;
                else
                    $scope.openEvents.reverse = !$scope.openEvents.reverse;
                $scope.openEvents.sortColumn = columnName;
            }

            $scope.select = function (patient) {
                $scope.selectedItem = null;
                $scope.productLevelResults = null;
                $scope.memberLevelResults = null;
                
                $http({
                    cache: false,
                    url: "/Welcome/MemberEligibilitySearch/",
                    method: "POST",
                    data: {
                        LAST_NAME: patient.LAST_NAME,
                        FIRST_NAME: patient.FIRST_NAME,
                        DOB: patient.DOB,
                        SUBSCRIBER_ID: null,
                        DATE_OF_SERVICE: patient.DATE_OF_SERVICE,
                        LOCATION_ID: patient.LOCATION_ID,
                        PROVIDER_ID: patient.PROVIDER_ID,
                        SSN: null,
                        ENROLLEE_ID: ($scope.isTherapy || $scope.isShowingLimitSearchResultsTo1) ? patient.ENROLLEE_ID : null,
                        Log: false
                    }
                }).then(function successCallback(response) {
                    if (response.data.EligibilityResultList.length == 1) {
                        var result = response.data.EligibilityResultList[0];
                        result.PROVIDER_ID = patient.PROVIDER_ID;
                        result.PROVIDER_NAME = patient.PROVIDER_NAME;
                        result.LOCATION_ID = patient.LOCATION_ID;
                        result.LOCATION_NAME = patient.LOCATION_NAME;
                        result.DATE_OF_SERVICE = patient.DATE_OF_SERVICE;

                        //result.STATUS = response.data.STATUS;
                        if (result.PRODUCTS != null && result.PRODUCTS.length > 1) {
                            $scope.productLevelResults = result.PRODUCTS;
                        }
                        else {
                            result.INSURER_ID = result.INSURER_ID;
                            result.INSURER_NAME = result.INSURER_NAME;
                            result.MEMBER_ID = result.MEMBER_ID;
                            result.PRODUCT_ID = result.PRODUCT_ID;
                            result.PRODUCT_NAME = result.PRODUCT_NAME;
                            $scope.productLevelResults = null;
                        }

                        $scope.showMemberAction(result, $scope.productLevelResults);
                    }
                    else {
                        $scope.showMemberLevelResults(response.data.EligibilityResultList, patient.DATE_OF_SERVICE);
                    }

                }, function errorCallback(response) {
                    console.error(response.data.Message);
                    console.error(response);
                    if ($scope.ExceptionDialogControl != null) {
                        $scope.ExceptionDialogControl.showDialog("Error with deleting member from calendar.");
                    }
                    else {
                        bootbox.alert(response.data.Message);
                    }
                });
            }
            //end DropDown

            $scope.verifyEligibilityBulk = function () {
                $scope.showBulkLoading = true;

                $http({
                    method: 'POST',
                    url: '/PatientManagement/VerifyEligibilityBulk',
                    params: {
                        LOCATION_ID: $scope.inputInfo.LOCATION_ID,
                        DATE_OF_SERVICE: $filter('date')($scope.calendarView[$scope.selectedRowIndex][$scope.selectedCellIndex].date._d, 'MM/dd/yyyy')
                    }
                }).then(function successCallback(response) {
                    $scope.showBulkLoading = false;

                    if (response.data.length > 0) {
                        angular.forEach($scope.openEvents, function (openEvent, value) {
                            var elig = _.find(response.data, function (item) {
                                return openEvent.LAST_NAME == item.LAST_NAME && openEvent.FIRST_NAME == item.FIRST_NAME && openEvent.DOB == item.DOB;
                            });
                            if (elig.ENROLLEE_COUNT > 1) {
                                openEvent.STATUS = 3;
                            }
                            else {
                                openEvent.STATUS = elig.STATUS;
                            }
                        });
                    }
                    else {
                        console.error(response.data.Message);
                        console.error(response);
                        if ($scope.ExceptionDialogControl != null) {
                            $scope.ExceptionDialogControl.showDialog("Error with bulk verifying eligibility.");
                        }
                        else {
                            bootbox.alert(response.data.Message);
                        }
                    }
                }, function errorCallback(response) {
                    console.error(response.data.Message);
                    console.error(response);
                    if ($scope.ExceptionDialogControl != null) {
                        $scope.ExceptionDialogControl.showDialog("Error with bulk verifying eligibility.");
                    }
                    else {
                        bootbox.alert(response.data.Message);
                    }
                });
            }

            $scope.openTab = function (url, sessionProperties, isExportToExcel) {
                var randomno = Math.floor((Math.random() * 100) + 1);
                var newWindow;
                if (isExportToExcel) {
                    newWindow = $window.open('');
                }
                else {
                    newWindow = $window.open('', 'PopUpWindow' + randomno, 'scrollbars=1,menubar=0,resizable=1,width=920,height=850');
                }

                var promise = $scope.setSessionProperties(sessionProperties);
                promise.then(function () {
                    newWindow.location = url;
                }, function (data) {
                    // bad, do nothing
                });
            }

            $scope.printCalendarRoster = function (isExportToExcel) {
                var dateOfService = $filter('date')($scope.calendarView[$scope.selectedRowIndex][$scope.selectedCellIndex].date._d, 'MM/dd/yyyy');
                
                var sessionProperties = [];
                var sessionProperty = {
                    SESSION_NAME: 'REPORT_PATIENT_CALENDAR_ROSTER_LOCATION_ID',
                    SESSION_VALUE: $scope.inputInfo.LOCATION_ID
                }
                sessionProperties.push(sessionProperty);

                var sessionProperty = {
                    SESSION_NAME: 'REPORT_PATIENT_CALENDAR_ROSTER_PROVIDER_ID',
                    SESSION_VALUE: $scope.inputInfo.PROVIDER_ID != -1 ? $scope.inputInfo.PROVIDER_ID : ""
                }
                sessionProperties.push(sessionProperty);

                var sessionProperty = {
                    SESSION_NAME: 'REPORT_PATIENT_CALENDAR_ROSTER_DATE_OF_SERVICE',
                    SESSION_VALUE: dateOfService
                }
                sessionProperties.push(sessionProperty);

                var sessionProperty = {
                    SESSION_NAME: 'REPORT_PATIENT_CALENDAR_ROSTER_IS_EXCEL',
                    SESSION_VALUE: isExportToExcel
                }
                sessionProperties.push(sessionProperty);

                $scope.openTab("/Areas/PWP/Reports/PatientCalendarRoster.aspx", sessionProperties, isExportToExcel);
            }

            $scope.setSessionProperties = function (sessionProperties) {
                var deferred = $q.defer();

                $http({
                    url: "/PortalWebSession/SetWebSessionProperties",
                    method: "PUT",
                    data: {
                        SESSION_PROPERTIES: sessionProperties
                    }
                }).then(function successCallback(response) {
                    if (!response.data.Status) {
                        console.error(response.data.Message);
                        console.error(response);
                        if ($scope.ExceptionDialogControl != null) {
                            $scope.ExceptionDialogControl.showDialog("Error with setting web session properties.");
                        }
                        else {
                            bootbox.alert(response.data.Message);
                        }
                        deferred.reject(false);
                    }
                    else {
                        deferred.resolve(true);
                    }
                }, function errorCallback(response) {
                    console.error(response.data.Message);
                    console.error(response);
                    if ($scope.ExceptionDialogControl != null) {
                        $scope.ExceptionDialogControl.showDialog("Error with setting web session properties.");
                    }
                    else {
                        bootbox.alert(response.data.Message);
                    }
                    deferred.reject(false);
                });

                return deferred.promise;
            }
        }]
    };
}]);

app.directive('wbxAddressFields', ['$http', '$timeout', function ($http, $timeout) {
    return {
        restrict: 'E',
        templateUrl: '/Templates/AddressFields',
        require: '^form',
        scope: {
            data: '=',
            control: '=',
            formType: '=?',
            stateList: '=?'
        },
        controller: ['$scope', function ($scope) {
        }],
        link: function (scope, element, attr, formController) {
            scope.address_form = formController;
            scope.control = scope.control || {};

            scope.control.populateStateList = function () {
                if (scope.stateList == null) {
                    scope.LoadingStateList = true;
                    $http({
                        method: 'GET',
                        url: '/PortalDropList/GetStates'
                    }).then(function successCallback(response) {
                        scope.stateList = response.data;
                        scope.LoadingStateList = false;
                    }, function errorCallback(response) {
                        console.error(response.data.Message);
                        console.error(response);
                        if ($scope.ExceptionDialogControl != null) {
                            $scope.ExceptionDialogControl.showDialog("Error with populating state dropdown.");
                        }
                        else {
                            bootbox.alert(response.data.Message);
                        }
                        scope.LoadingStateList = false;
                    });
                }
            }
        }
    };
}]);

//TODO: Remove this. But we have to take care of the vision contacts alternate shipping first.
//Make sure to remove all the .cs methods if they are not used anymore. ie: DropList/GetLanguages
app.directive('wbxPayeeLocationForm', ['$http', '$timeout', function ($http, $timeout) {
    return {
        restrict: 'E',
        templateUrl: '/Templates/PayeeLocationForm',
        scope: {
            data: '=',
            formType: '=',
            isVision: '=?',
            cancelButton: '&',
            submitButton: '&'
        },
        controller: ['$scope', function ($scope) {
            $scope.init = function () {
                $scope.populateStateList();
            }

            $scope.populateStateList = function () {
                $scope.stateList = null;
                $http({
                    method: 'GET',
                    url: '/PortalDropList/GetStates'
                }).then(function successCallback(response) {
                    $scope.stateList = response.data;
                }, function errorCallback(response) {
                    console.error(response.data.Message);
                    console.error(response);
                    if ($scope.ExceptionDialogControl != null) {
                        $scope.ExceptionDialogControl.showDialog("Error with populating state dropdown.");
                    }
                    else {
                        bootbox.alert(response.data.Message);
                    }
                });
            }

            $scope.submit = function () {
                if ($scope.payee_location_form.$invalid) {
                    return false;
                }
                $scope.payee_location_form.$setPristine();

                if ($scope.isVision && $scope.formType != 'shipping') {
                    //Convert location hours
                    $scope.data.LOCATION_HOURS = [];
                    _.each($scope.data.HOURS, function (obj, idx) {
                        $scope.data.LOCATION_HOURS.push({ DAY: idx, HR_END1: obj.HR_END1, HR_END2: obj.HR_END2, HR_START1: obj.HR_START1, HR_START2: obj.HR_START2 });
                    });
                }

                $scope.submitButton({ data: $scope.data });
            }

            $scope.cancel = function () {
                //If it's not a valid email, it has to be explicitly cleared because 
                // angular doesn't bind until the value is valid.
                //In this case, if it's not a valid email, angular doesn't bind it and 
                // it's not automatically cleared.
                if ($scope.payee_location_form.emailTextBox.$invalid) {
                    $('#emailTextBox')[0].value = "";
                }

                $scope.payee_location_form.$setPristine();
                $scope.cancelButton();
            }

            $scope.remove = function () {
                $scope.payee_location_form.$setPristine();
                $scope.submitButton({ data: null });
            }

            $scope.getLanguages = function () {
                $scope.loadingLanguagesDropDown = true;
                $http({
                    method: 'GET',
                    url: '/DropList/GetLanguages'
                }).then(function successCallback(response) {
                    $scope.loadingLanguagesDropDown = false;
                    $scope.languageList = response.data;
                    $scope.setSelect2_Language();
                }, function errorCallback(response) {
                    console.error(response.data.Message);
                    console.error(response);
                    if ($scope.ExceptionDialogControl != null) {
                        $scope.ExceptionDialogControl.showDialog("Error with populating language dropdown.");
                    }
                    else {
                        bootbox.alert(response.data.Message);
                    }
                    $scope.loadingLanguagesDropDown = false;
                });
            }

            $scope.setSelect2_Language = function () {
                $(".wbx-select2-language").select2();
            }

            $scope.$watchCollection('isVision + formType', function (n, o) {
                if ($scope.isVision && $scope.formType == 'location' && $scope.formType != 'shipping') {
                    $scope.getLanguages();
                }
            });

            $scope.$watchCollection('data.LANGUAGES', function (n, o) {
                $timeout(function () {
                    $scope.setSelect2_Language();
                }, 100);
            });
        }]
    };
}]);

app.directive('wbxProviderForm', ['$http', '$timeout', function ($http, $timeout) {
    return {
        restrict: 'E',
        templateUrl: '/Templates/ProviderForm',
        scope: {
            providerData: '=',
            isVision: '=',
            cancelButton: '&',
            submitButton: '&'
        },
        controller: ['$scope', function ($scope) {
            $scope.submit = function () {
                if ($scope.provider_form.$invalid) {
                    return false;
                }
                $scope.provider_form.$setPristine();
                $scope.submitButton({ data: $scope.providerData });
            }

            $scope.cancel = function () {
                //If it's not a valid email, it has to be explicitly cleared because 
                // angular doesn't bind until the value is valid.
                //In this case, if it's not a valid email, angular doesn't bind it and 
                // it's not automatically cleared.
                if ($scope.provider_form.emailTextBox.$invalid) {
                    $('#emailTextBox')[0].value = "";
                }

                $scope.provider_form.$setPristine();
                $scope.cancelButton();
            }

            $scope.getSpecialties = function () {
                $scope.loadingSpecialtiesDropDown = true;
                $http({
                    method: 'GET',
                    url: '/DropList/GetSpecialties'
                }).then(function successCallback(response) {
                    $scope.loadingSpecialtiesDropDown = false;
                    $scope.specialtyList = response.data;
                    $scope.setSelect2_Specialty();
                }, function errorCallback(response) {
                    console.error(response.data.Message);
                    console.error(response);
                    if ($scope.ExceptionDialogControl != null) {
                        $scope.ExceptionDialogControl.showDialog("Error with populating specialty dropdown.");
                    }
                    else {
                        bootbox.alert(response.data.Message);
                    }
                    $scope.loadingSpecialtiesDropDown = false;
                });
            }

            $scope.setSelect2_Specialty = function () {
                $(".wbx-select2-specialty").select2({ tags: true });
            }

            $scope.$watch('isVision', function (n, o) {
                if (n) {
                    $scope.getSpecialties();
                }
            });

            $scope.$watchCollection('providerData.SPECIALTIES', function (n, o) {
                $timeout(function () {
                    $scope.setSelect2_Specialty();
                }, 100);
            });

        }]
    };
}]);

app.directive('wbxOfficeContactFormDialog', ['$http', '$timeout', function ($http, $timeout) {
    return {
        restrict: 'E',
        templateUrl: '/Templates/OfficeContactFormDialog',
        scope: {
            control: '=',
            officeContactData: '=',
            isEdit: '=',
            isImpersonation: '=',
            submitButton: '&',
            cancelButton: '&?'
        },
        controller: ['$scope', function ($scope) {
            $scope.submit = function () {
                if (!$scope.isImpersonation) {

                    if ($scope.office_contact_form.$invalid) {
                        return false;
                    }

                    $scope.ShowCreatingOfficeContactProcessingMsg = true;

                    //If it's an empty string, store as NULL in the database
                    if ($scope.officeContactData.EMAIL != null && $scope.officeContactData.EMAIL.trim() == '') {
                        $scope.officeContactData.EMAIL = null;
                    }

                    if (!$scope.isEdit) {
                        //Create
                        $http({
                            url: "/EntityManagement/CreateOfficeContact",
                            method: "PUT",
                            data: {
                                LOCATION_ID: $scope.officeContactData.LOCATION_ID,
                                FIRST_NAME: $scope.officeContactData.FIRST_NAME,
                                LAST_NAME: $scope.officeContactData.LAST_NAME,
                                VOICE_PHONE: $scope.officeContactData.VOICE_PHONE,
                                FAX_PHONE: $scope.officeContactData.FAX_PHONE,
                                EMAIL: $scope.officeContactData.EMAIL
                            }
                        }).then(function successCallback(response) {
                            $scope.ShowCreatingOfficeContactProcessingMsg = false;
                            if (!response.data.Status) {
                                console.error(response.data.Message);
                                console.error(response);
                                if ($scope.ExceptionDialogControl != null) {
                                    $scope.ExceptionDialogControl.showDialog("Error with creating office contact.");
                                }
                                else {
                                    bootbox.alert(response.data.Message);
                                }
                            }
                            else {
                                $scope.officeContactData.OFFICE_CONTACT_ID = response.data.Data.OFFICE_CONTACT_ID;
                                $scope.control.hideDialog();
                            }
                            $scope.submitButton({ data: $scope.officeContactData });
                        }, function errorCallback(response) {
                            console.error(response.data.Message);
                            console.error(response);
                            if ($scope.ExceptionDialogControl != null) {
                                $scope.ExceptionDialogControl.showDialog("Error with creating office contact.");
                            }
                            else {
                                bootbox.alert(response.data.Message);
                            }
                            $scope.ShowCreatingOfficeContactProcessingMsg = false;
                        });
                    }
                    else {
                        //Edit
                        $http({
                            url: "/EntityManagement/UpdateOfficeContact",
                            method: "PUT",
                            data: {
                                OFFICE_CONTACT_ID: $scope.officeContactData.OFFICE_CONTACT_ID,
                                FIRST_NAME: $scope.officeContactData.FIRST_NAME,
                                LAST_NAME: $scope.officeContactData.LAST_NAME,
                                VOICE_PHONE: $scope.officeContactData.VOICE_PHONE,
                                FAX_PHONE: $scope.officeContactData.FAX_PHONE,
                                EMAIL: $scope.officeContactData.EMAIL
                            }
                        }).then(function successCallback(response) {
                            $scope.ShowCreatingOfficeContactProcessingMsg = false;
                            if (!response.data.Status) {
                                console.error(response.data.Message);
                                console.error(response);
                                if ($scope.ExceptionDialogControl != null) {
                                    $scope.ExceptionDialogControl.showDialog("Error with updating office contact.");
                                }
                                else {
                                    bootbox.alert(response.data.Message);
                                }
                            }
                            else {
                                $scope.control.hideDialog();
                            }

                            $scope.submitButton({ data: $scope.officeContactData });
                        }, function errorCallback(response) {
                            console.error(response.data.Message);
                            console.error(response);
                            if ($scope.ExceptionDialogControl != null) {
                                $scope.ExceptionDialogControl.showDialog("Error with updating office contact.");
                            }
                            else {
                                bootbox.alert(response.data.Message);
                            }
                            $scope.ShowCreatingOfficeContactProcessingMsg = false;
                        });
                    }

                    $scope.office_contact_form.$setPristine();
                }
            }

            $scope.cancel = function () {
                //If it's not a valid email, it has to be explicitly cleared because 
                // angular doesn't bind until the value is valid.
                //In this case, if it's not a valid email, angular doesn't bind it and 
                // it's not automatically cleared.
                if ($scope.office_contact_form.emailTextBox.$invalid) {
                    $('#emailTextBox')[0].value = "";
                }

                $scope.ShowCreatingOfficeContactProcessingMsg = false;
                $scope.office_contact_form.$setPristine();
                $scope.control.hideDialog();
                if ($scope.cancelButton != null) {
                    $scope.cancelButton();
                }
            }
        }],
        link: function (scope, element, attr) {
            scope.control = scope.control || {};
            scope.control.showDialog = function () {
                $('#office-contact-dialog').modal({
                    backdrop: 'static'
                });
                $('#office-contact-dialog').modal('show');
            };

            scope.control.hideDialog = function () {
                $('#office-contact-dialog').modal('hide');
            };
        }
    };
}]);

app.directive('wbxSelectGroupDialog', ['$http', '$timeout', '$window', function ($http, $timeout, $window) {
    return {
        restrict: 'E',
        templateUrl: '/Templates/SelectGroupDialog',
        scope: {
            selectgroupData: '=',
            alerts: '=',
            alertMessages: '=',
            openClose: '=',
            redirect: '=',
            cancelButton: '&',
            submitButton: '&'
        },
        controller: ['$scope', function ($scope) {
            $scope.submit = function () {
                if ($scope.selectgroup_form.$invalid) {
                    return false;
                }
                $scope.selectgroup_form.$setPristine();
                $scope.submitButton({ data: $scope.selectgroupData });
            }

            $scope.cancel = function () {
                //console.log("shared directive cancel()");
                //// prevent cancel
                //$scope.selectgroup_form.$setPristine();
                //$scope.cancelButton();
            }

            $scope.setgroup = function (groupId, planId) {
                //console.log("User selected group: " + groupId + " planId: " + planId + " reload: " + $scope.reload);
                $timeout(function () {
                    $http({
                        method: 'PUT',
                        url: '/MWP/EnrollmentSummary/SetGroup',
                        params: {
                            groupId: groupId
                            ,planId: planId
                        }
                    }).then(function (data) {
                        data = data.data;
                        $scope.cancel();
                        $scope.openClose = false;
                        if ($scope.redirect != "") {
                            $window.location = $scope.redirect;
                        }

                    }, function (data, status, headers, config) {
                        bootbox.alert(data);
                    });
                });

            }

            $scope.$watch('selectgroup_form.$pristine', function (n, o) {
                if (n != o && !n) {
                    $scope.alerts = {};
                    $scope.alertMessages = {};
                }
            });

            $scope.$watch('openClose', function (n, o) {
                if (n != null) {
                    if (n) {
                        //console.log("open select dialog" + n);
                        //open the dialog
                        $('#selectgroup-dialog').modal({
                            keyboard: false,
                            backdrop: 'static'
                        })

                        // get group information
                        $http({
                            method: 'GET',
                            url: '/MWP/EnrollmentSummary/GetGroups',
                        }).then(function (data) {
                            $scope.groupsList = data.data;
                        }, function (data, status, headers, config) {
                            bootbox.alert(data);
                        });

                        $('#selectgroup-dialog').modal('show');
                    }
                    else {
                        $('#selectgroup-dialog').modal('hide');
                        //console.log("return url:" + $scope.returnUrl)
                        //if ($scope.returnUrl != null) {
                        //    scope.$apply(function () { $location.path($scope.returnUrl); });
                        //}
                    }
                }
            });
        }]
    };
}]);

app.directive('wbxClaimAuthSearchCriteria' , ['$location', function ($location) {
    return {
        restrict: 'E',
        templateUrl: '/Templates/ClaimAuthSearchCriteria',
        scope: {
            statusList: '=',
            isClaim: '=', /*true => Claims. false => Authorizations*/
            searchResults: '=',
            showSearchResultsLoading: '=',
            searchText: '=',
            sessions: '='
        },
        controller: ['$scope', '$http', '$location', '$timeout', 'GoogleTagManagerService', function ($scope, $http, $location, $timeout, googleTagManagerService)
        {
            $scope.searchCriteria = {};
            $scope.collapsePanels = {
                isCollapsed : false
            };

            $scope.init = function (isInitial) {
                $scope.ShowSearchCriteria = true;
                $scope.clearSearchCriteria();
                $scope.searchResults = null;
                $scope.searchText = '';

                if (isInitial) {
                    if($scope.isClaim){
                        googleTagManagerService.setPageInfo('Claim Search');
                    }
                    else {
                        googleTagManagerService.setPageInfo('Authorization Search');
                    }

                    $timeout(function () {
                        if ($scope.sessions.IS_FACILITY_SUBTYPE) {
                            $(".wbx-select2-facility").select2();
                        }
                        else {
                            $(".wbx-select2-location").select2();
                            $(".wbx-select2-provider").select2();
                        }
                    });
                    
                    $scope.populateStatusList();
                    $scope.populateSearchCriteriaList();
                }
                else {
                    if ($scope.sessions.IS_FACILITY_SUBTYPE) {
                        $scope.autoSetFacility();
                    }
                    else {
                        $scope.autoSetLocation();
                        $scope.autoSetProvider();
                    }
                    $scope.autoSetInsurer();
                    $scope.autoSetProcessingStatus();
                }
            }

            $scope.autoSetLocation = function () {
                if ($scope.LocationList.length == 2) {
                    $scope.searchCriteria.LOCATION_ID = $scope.LocationList[1].LOCATION_ID;
                }
                else {
                    $scope.searchCriteria.LOCATION_ID = -1;
                }
                $scope.setSelect2_Location();
                $scope.IsLocationSet = true;
            }

            $scope.autoSetProvider = function () {
                if ($scope.ProviderList.length == 2) {
                    $scope.searchCriteria.PROVIDER_ID = $scope.ProviderList[1].PROVIDER_ID;
                }
                else {
                    $scope.searchCriteria.PROVIDER_ID = -1;
                }

                $scope.setSelect2_Provider();
                $scope.IsProviderSet = true;
            }

            $scope.autoSetFacility = function () {
                if ($scope.FacilityList.length == 2) {
                    $scope.searchCriteria.FACILITY_ID = $scope.FacilityList[1].FACILITY_ID;
                }
                else {
                    $scope.searchCriteria.FACILITY_ID = -1;
                }

                $scope.setSelect2_Facility();
                $scope.IsFacilitySet = true;
            }

            $scope.autoSetInsurer = function () {
                if ($scope.InsurerList.length == 1) {
                    angular.forEach($scope.InsurerList, function (insurer, key) {
                        if (insurer.INSURER_ID == $scope.InsurerList[0].INSURER_ID) {
                            $scope.searchCriteria.insurer = insurer;
                        }
                    });
                }
                $scope.IsInsurerSet = true;
            }

            $scope.autoSetProcessingStatus = function () {
                if ($scope.statusList.length == 1) {
                    angular.forEach($scope.statusList, function (status, key) {
                        if (status.PORTAL_STATUS == $scope.statusList[0].PORTAL_STATUS) {
                            $scope.searchCriteria.Status = status;
                        }
                    });
                }
                $scope.IsProcessingStatusSet = true;
            }

            $scope.setSelect2_Location = function () {
                $timeout(function () {
                    $(".wbx-select2-location").select2({
                        escapeMarkup: function (m) { return m; },
                        templateResult: function (data) {
                            if (data.text == "") {
                                return;
                            }

                            if (data.id == -1) {
                                return $("<span><b>" + data.text + "</b> <br /></span>");
                            }
                            else {
                                var str = "";
                                var result = _.findWhere($scope.LocationList, { LOCATION_ID: parseInt(data.id) });
                                if (result != null) {
                                    str = $("<span><b>" + result.NAME + "</b> <br />" + result.ADDRESS1 + ", " + result.CITY + ", " + result.STATE + " " + result.ZIP + "</span>");
                                }
                                return str;
                            }
                        },
                        templateSelection: function (data) {
                            var str = "";

                            var result = _.findWhere($scope.LocationList, { LOCATION_ID: $scope.searchCriteria.LOCATION_ID });
                            if (result != null) {
                                if (result.LOCATION_ID == -1) {
                                    str = result.NAME;
                                }
                                else {
                                    str = $("<span title=\"" + result.NAME + "&#10;" + result.ADDRESS1 + " " + result.CITY + " " + result.STATE + "," + result.ZIP + "" + "\"><b>" + result.NAME + "</b> (" + result.CITY + ", " + result.STATE + ", " + result.ZIP + ")</span>");
                                }
                            }
                        
                            return str;
                        }
                    });
                });
            }

            $scope.setSelect2_Provider = function () {
                $timeout(function () {
                    $(".wbx-select2-provider").select2({
                        escapeMarkup: function (m) { return m; },
                        templateResult: function (data) {
                            if (data.text == "") {
                                return;
                            }
                            else {
                                return data.text;
                            }
                        },
                        templateSelection: function (data) {
                            var str = "";

                            var result = _.findWhere($scope.ProviderList, { PROVIDER_ID: $scope.searchCriteria.PROVIDER_ID });
                            if (result != null) {
                                str = $("<span title=\"" + result.FIRST_NAME + ' ' + result.LAST_NAME + "\">" + result.FIRST_NAME + ' ' + result.LAST_NAME + "</span>");
                            }
                        
                            return str;
                        }
                    });
                });
            }

            $scope.setSelect2_Facility = function () {
                $timeout(function () {
                    $(".wbx-select2-facility").select2({
                        escapeMarkup: function (m) { return m; },
                        templateResult: function (data) {
                            if (data.text == "") {
                                return;
                            }

                            if (data.id == -1) {
                                return $("<span><b>" + data.text + "</b> <br /></span>");
                            }
                            else {
                                var str = "";
                                var result = _.findWhere($scope.FacilityList, { FACILITY_ID: parseInt(data.id) });
                                if (result != null) {
                                    str = $("<span><b>" + result.NAME + "</b> <br />" + result.ADDRESS1 + ", " + result.CITY + ", " + result.STATE + " " + result.ZIP + "</span>");
                                }
                                return str;
                            }
                        },
                        templateSelection: function (data) {
                            var str = "";
                            var result = _.findWhere($scope.FacilityList, { FACILITY_ID: $scope.searchCriteria.FACILITY_ID });
                            if (result != null) {
                                if (result.FACILITY_ID == -1) {
                                    str = result.NAME;
                                }
                                else {
                                    str = $("<span title=\"" + result.NAME + "&#10;" + result.ADDRESS1 + " " + result.CITY + " " + result.STATE + "," + result.ZIP + "" + "\"><b>" + result.NAME + "</b> (" + result.CITY + ", " + result.STATE + ", " + result.ZIP + ")</span>");
                                }
                            }
                            return str;
                        }
                    });
                });
            }

            $scope.showResults = function () {
                console.log($scope.searchResults);
            }

             $scope.formErrors = function (formField, errorList, formError){
                for (var i = 0; i < formError.length; i++) {
                    errorList.push({
                        'form field': formField,
                        'name': formError[i].$name,
                        'untouched': formError[i].$untouched,
                        'touched': formError[i].$touched,
                        'pristine': formError[i].$pristine,
                        'dirty': formError[i].$dirty,
                        'valid': formError[i].$valid,
                        'invalid': formError[i].$invalid,
                        'error': formError[i].$error,
                        'success': formError[i].$success
                    });
                }
                return errorList;
            }

            $scope.performSearch = function () {

                googleTagManagerService.setClickInfo('click', 'claim search', 'search button', 'field_interaction', '' , 'button', 'search');

                if ($scope.search_form.$invalid) {

                    var errorList = [];
                    if ($scope.search_form.$error.hasOwnProperty('isAfter')) {
                        $scope.formErrors('isAfter', errorList, $scope.search_form.$error.isAfter);
                    }
                    if ($scope.search_form.$error.hasOwnProperty('isNotFuture')) {
                        $scope.formErrors('isNotFuture', errorList, $scope.search_form.$error.isNotFuture);
                    }

                    googleTagManagerService.setClickInfo('error', 'claim search', 'search button', 'field_interaction', errorList , 'button', 'search');

                    return true;
                }
                $scope.searchResults = [];
                $scope.showSearchResultsLoading = true;

                if ($scope.isClaim) {
                    //Claims
                    $http({
                        method: 'GET',
                        url: '/ClaimAuthSearch/SearchClaims',
                        params: {
                            PORTAL_STATUS: $scope.searchCriteria.Status != null ? $scope.searchCriteria.Status.PORTAL_STATUS : null,
                            ENCOUNTER_ID: $scope.searchCriteria.ENCOUNTER_ID,
                            SERVICE_DATE_FROM: $scope.searchCriteria.SERVICE_DATE_FROM,
                            SERVICE_DATE_TO: $scope.searchCriteria.SERVICE_DATE_TO,
                            ENTERED_DATE_FROM: $scope.searchCriteria.ENTERED_DATE_FROM,
                            ENTERED_DATE_TO: $scope.searchCriteria.ENTERED_DATE_TO,
                            DATE_PAID_FROM: $scope.searchCriteria.DATE_PAID_FROM,
                            DATE_PAID_TO: $scope.searchCriteria.DATE_PAID_TO,
                            FIRST_NAME: $scope.searchCriteria.FIRST_NAME,
                            LAST_NAME: $scope.searchCriteria.LAST_NAME,
                            SUBSCRIBER_ID: $scope.searchCriteria.SUBSCRIBER_ID,
                            MEMBER_ID: $scope.searchCriteria.MEMBER_ID,
                            INSURER_ID: $scope.searchCriteria.insurer != null ? $scope.searchCriteria.insurer.INSURER_ID : null,
                            LOCATION_ID: $scope.searchCriteria.LOCATION_ID != -1 ? $scope.searchCriteria.LOCATION_ID : null,
                            PROVIDER_ID: $scope.searchCriteria.PROVIDER_ID != -1 ? $scope.searchCriteria.PROVIDER_ID : null,
                            FACILITY_ID: $scope.searchCriteria.FACILITY_ID != -1 ? $scope.searchCriteria.FACILITY_ID : null
                        }
                    }).then(function successCallback(response) {

                        googleTagManagerService.setClickInfo('success', 'claim search', 'search button', 'field_interaction', 'search generated successfully' , 'button', 'search');

                        if (response.data.length > 0) {
                            $scope.searchResults = response.data;
                        }

                        $timeout(function () {
                            $('html, body').animate({
                                scrollTop: $('#claim-auth-results').offset().top
                            }, 750);
                        }, 250);

                        $scope.showSearchResultsLoading = false;
                        $scope.search_form.$setPristine();
                    }, function errorCallback(response) {

                        console.error(response.data.Message);
                        console.error(response);
                        if ($scope.ExceptionDialogControl != null) {

                            googleTagManagerService.setClickInfo('error', 'claim search', 'search button', 'field_interaction', 'error with claim search' , 'button', 'search');

                            $scope.ExceptionDialogControl.showDialog("Error with claim search.");
                        }
                        else {

                            googleTagManagerService.setClickInfo('error', 'claim search', 'search button', 'field_interaction', ((response.data.Message) ? response.data.Message.toLowerCase() : "an error has occurred"), 'button', 'search');

                            bootbox.alert(response.data.Message);
                        }
                        $scope.showSearchResultsLoading = false;
                        $scope.search_form.$setPristine();
                    });
                }
                else {
                    //Authorizations
                    $http({
                        method: 'GET',
                        url: '/ClaimAuthSearch/SearchAuths',
                        params: {
                            AUTHORIZATION_STATUS_ID: $scope.searchCriteria.Status != null ? $scope.searchCriteria.Status.PORTAL_STATUS : null,
                            AUTHORIZATION_NUMBER: $scope.searchCriteria.AUTHORIZATION_NUMBER,
                            SERVICE_DATE_FROM: $scope.searchCriteria.ANTICIPATED_SERVICE_DATE_FROM,
                            SERVICE_DATE_TO: $scope.searchCriteria.ANTICIPATED_SERVICE_DATE_TO,
                            ENTERED_DATE_FROM: $scope.searchCriteria.ENTERED_DATE_FROM,
                            ENTERED_DATE_TO: $scope.searchCriteria.ENTERED_DATE_TO,
                            DETERMINATION_DATE_FROM: $scope.searchCriteria.DETERMINATION_DATE_FROM,
                            DETERMINATION_DATE_TO: $scope.searchCriteria.DETERMINATION_DATE_TO,
                            FIRST_NAME: $scope.searchCriteria.FIRST_NAME,
                            LAST_NAME: $scope.searchCriteria.LAST_NAME,
                            SUBSCRIBER_ID: $scope.searchCriteria.SUBSCRIBER_ID,
                            MEMBER_ID: $scope.searchCriteria.MEMBER_ID,
                            INSURER_ID: $scope.searchCriteria.insurer != null ? $scope.searchCriteria.insurer.INSURER_ID : null,
                            LOCATION_ID: $scope.searchCriteria.LOCATION_ID != -1 ? $scope.searchCriteria.LOCATION_ID : null,
                            PROVIDER_ID: $scope.searchCriteria.PROVIDER_ID != -1 ? $scope.searchCriteria.PROVIDER_ID : null
                        }
                    }).then(function successCallback(response) {
                        if (response.data.length > 0) {

                            googleTagManagerService.setClickInfo('success', 'claim search', 'search button', 'field_interaction', 'search generated successfully' , 'button', 'search');

                            $scope.searchResults = response.data;
                            if ($scope.sessions.IS_THERAPY) {
                                //For therapy, handling treatment type with multiple lines of business
                                angular.forEach($scope.searchResults, function (result) {
                                    if (result.IS_MULTIPLE_SERVICE_LINES) {
                                        result.Italicize = { 'font-style': 'italic' };
                                        result.TREATMENT_TYPE = '(Multiple)';
                                        result.TT_SORT = 'Multiple';
                                        result.TT_SEARCH = '(Multiple)';
                                    }
                                    else if (result.TREATMENT_TYPE == 'SP') {
                                        result.TREATMENT_TYPE = 'Splint';
                                        result.TT_SORT = 'Splint';
                                        result.TT_SEARCH = 'Splint';
                                    }

                                    var today = moment().startOf('day');
                                    var dateOfServiceFrom = moment(result.DATE_OF_SERVICE_FROM, "MM/DD/YYYY").startOf('day');
                                    var dateOfServiceTo;

                                    //Only enable if the date of service is not in the future.
                                    result.EnableStartClaim = dateOfServiceFrom <= today;
                                });
                            }
                        }

                        $timeout(function () {
                            $('html, body').animate({
                                scrollTop: $('#claim-auth-results').offset().top
                            }, 750);
                        }, 250);

                        $scope.showSearchResultsLoading = false;
                        $scope.search_form.$setPristine();
                    }, function errorCallback(response) {
                        console.error(response.data.Message);
                        console.error(response);
                        if ($scope.ExceptionDialogControl != null) {

                            googleTagManagerService.setClickInfo('error', 'claim search', 'search button', 'field_interaction', 'error with auth search' , 'button', 'search');

                            $scope.ExceptionDialogControl.showDialog("Error with auth search.");
                        }
                        else {

                            googleTagManagerService.setClickInfo('error', 'claim search', 'search button', 'field_interaction', ((response.data.Message) ? response.data.Message.toLowerCase() : "an error has occurred"), 'button', 'search');

                            bootbox.alert(response.data.Message);
                        }
                        $scope.showSearchResultsLoading = false;
                        $scope.search_form.$setPristine();
                    });
                }
            }  

            $scope.clear = function () {
                
                googleTagManagerService.setClickInfo('click', 'claim search', 'clear filters button', 'field_interaction', '' , 'button', 'clear filters');

                $scope.init(false);
                $scope.search_form.$setPristine();
            }

            $scope.populateStatusList = function () {
                if ($scope.isClaim) {
                    $scope.StatusesToLoad = [
                                    {
                            PORTAL_PROCESSING_TYPE: 1,
                            TITLE: 'Claim Status'
                            }
                    ];
                            }
                else {
                    $scope.StatusesToLoad = [
                        {
                            PORTAL_PROCESSING_TYPE: 2,
                            TITLE: 'Authorization Status'
                        }
                    ];
                    }
            }

            $scope.clearSearchCriteria = function () {
                $scope.searchCriteria.Status = null;
                if ($scope.InsurerList != null && $scope.InsurerList.length > 1) {
                    $scope.searchCriteria.insurer = null;
                }

                $scope.searchCriteria.ENCOUNTER_ID = '';
                $scope.searchCriteria.AUTHORIZATION_NUMBER = '';
                $scope.searchCriteria.SERVICE_DATE_FROM = '';
                $scope.searchCriteria.SERVICE_DATE_TO = '';
                $scope.searchCriteria.ANTICIPATED_SERVICE_DATE_FROM = '';
                $scope.searchCriteria.ANTICIPATED_SERVICE_DATE_TO = '';
                $scope.searchCriteria.ENTERED_DATE_FROM = '';
                $scope.searchCriteria.ENTERED_DATE_TO = '';
                $scope.searchCriteria.DATE_PAID_FROM = '';
                $scope.searchCriteria.DATE_PAID_TO = '';
                $scope.searchCriteria.DETERMINATION_DATE_FROM = '';
                $scope.searchCriteria.DETERMINATION_DATE_TO = '';

                $scope.searchCriteria.FIRST_NAME = '';
                $scope.searchCriteria.LAST_NAME = '';
                $scope.searchCriteria.SUBSCRIBER_ID = '';
                $scope.searchCriteria.MEMBER_ID = '';

                if ($scope.sessions.IS_FACILITY_SUBTYPE) {
                    if ($scope.FacilityList != null && $scope.FacilityList.length > 2 && $scope.searchCriteria.FACILITY_ID != -1) {
                        //Only set to "All" option if they are more than 1 facility and it's not set to all yet
                        $scope.searchCriteria.FACILITY_ID = -1;
                        $scope.setSelect2_Facility();
                    }
                }
                else {
                    if ($scope.searchCriteria.LOCATION_ID != null &&
                        $scope.searchCriteria.PROVIDER_ID != null) {

                        if ($scope.searchCriteria.LOCATION_ID == -1 &&
                           (($scope.ProviderList.length == 2 && $scope.searchCriteria.PROVIDER_ID != $scope.ProviderList[1].PROVIDER_ID) ||
                            ($scope.ProviderList.length != 2 && $scope.searchCriteria.PROVIDER_ID != -1))) {
                            //Location has All selected and Provider has more than one and other than All is selected
                            if ($scope.ProviderList.length == 2) {
                                $scope.searchCriteria.PROVIDER_ID = $scope.ProviderList[1].PROVIDER_ID;
                            }
                            else {
                                $scope.searchCriteria.PROVIDER_ID = -1;
                            }

                            $scope.setSelect2_Provider();
                        }
                        else if (($scope.LocationList.length == 2 && $scope.searchCriteria.LOCATION_ID != $scope.LocationList[1].LOCATION_ID) ||
                                 ($scope.LocationList.length != 2 && $scope.searchCriteria.LOCATION_ID != -1)) {
                            $scope.searchCriteria.LOCATION_ID = -1;
                            $scope.setSelect2_Location();
                            $scope.populateProviderList();
                        }
                    }
                }
            }

            $scope.populateSearchCriteriaList = function () {
                var dropdownSettings = {};

                if ($scope.sessions.IS_FACILITY_SUBTYPE) {
                    $scope.FacilityList = null;
                    $scope.LoadingFacilityDropDown = true;

                    dropdownSettings = {
                        GET_FACILITY: true,
                        INCLUDE_FACILITY_OPTION_ALL: true
                    }
                }
                else {
                    $scope.LocationList = null;
                    $scope.ProviderList = null;

                    $scope.LoadingLocationDropDown = true;
                    $scope.LoadingProviderDropDown = true;

                    dropdownSettings = {
                        GET_LOCATION: true,
                        INCLUDE_LOCATION_OPTION_ALL: true,
                        GET_PROVIDER: true,
                        INCLUDE_PROVIDER_OPTION_ALL: true
                    }
                }
                
                $scope.InsurerList = null;
                $scope.LoadingInsurerDropDown = true;
                dropdownSettings.GET_INSURER = true;

                $http({
                    method: 'GET',
                    url: '/DropList/GetSearchCriteriaDropdowns',
                    params: {
                        GET_LOCATION: dropdownSettings.GET_LOCATION,
                        INCLUDE_LOCATION_OPTION_ALL: dropdownSettings.INCLUDE_LOCATION_OPTION_ALL,
                        GET_PROVIDER: dropdownSettings.GET_PROVIDER,
                        INCLUDE_PROVIDER_OPTION_ALL: dropdownSettings.INCLUDE_PROVIDER_OPTION_ALL,
                        GET_FACILITY: dropdownSettings.GET_FACILITY,
                        INCLUDE_FACILITY_OPTION_ALL: dropdownSettings.INCLUDE_FACILITY_OPTION_ALL,
                        GET_INSURER: dropdownSettings.GET_INSURER
                    }
                }).then(function successCallback(response) {

                    if ($scope.sessions.IS_FACILITY_SUBTYPE) {
                        $scope.FacilityList = response.data.FacilitiesList;
                        $scope.autoSetFacility();
                        $scope.LoadingFacilityDropDown = false;
                    }
                    else {
                        $scope.LocationList = response.data.LocationsList;
                        $scope.ProviderList = response.data.ProvidersList;
                        $scope.autoSetLocation();
                        $scope.autoSetProvider();
                        $scope.LoadingLocationDropDown = false;
                        $scope.LoadingProviderDropDown = false;
                    }

                    $scope.InsurerList = response.data.InsurerList;
                    $scope.autoSetInsurer();
                    $scope.LoadingInsurerDropDown = false;

                }, function errorCallback(response) {
                    console.error(response.data.Message);
                    console.error(response);
                    $scope.ExceptionDialogControl.showDialog("Error with populating Search Criteria dropdowns.");

                    $scope.LoadingLocationDropDown = false;
                    $scope.LoadingProviderDropDown = false;
                    $scope.LoadingFacilityDropDown = false;
                    $scope.LoadingInsurerDropDown = false;

                });
            }

            $scope.locationListOnChange = function () {
                $scope.populateProviderList();
            }

            $scope.populateProviderList = function () {
                $scope.LoadingProviderDropDown = true;

                $http({
                    method: 'GET',
                    url: '/DropList/GetProviders',
                    params: {
                        locationId: $scope.searchCriteria.LOCATION_ID != -1 ? $scope.searchCriteria.LOCATION_ID : null,
                        includeOptionAll: true
                    }
                }).then(function successCallback(response) {
                    $scope.ProviderList = response.data;
                    $scope.LoadingProviderDropDown = false;
                    $scope.autoSetProvider();
                }, function errorCallback(response) {
                    console.error(response.data.Message);
                    console.error(response);
                    if ($scope.ExceptionDialogControl != null) {
                        $scope.ExceptionDialogControl.showDialog("Error with populating provider dropdown.");
                    }
                    else {
                        bootbox.alert(response.data.Message);
                    }
                    $scope.LoadingProviderDropDown = false;
                });
            }
            
            $scope.$watch('search_form.$pristine', function (n, o) {
                if (n != o && !n && ($scope.searchResults != null)) {
                    $scope.searchResults = null;
                    $scope.searchText = '';
                }
            });

            $scope.showProcessingStatusDescription = function () { 
            
                var pageview = "claim status modal";
                if ($location.absUrl().indexOf("/ClaimDashboard") > -1) {
                   pageview = "dashboard"
                }

                if ($location.absUrl().indexOf("/ClaimSearch") > -1) {
                   pageview = "claim search"
                }

                googleTagManagerService.setClickInfo('click', pageview, 'claim status link', 'open_modal', '', 'link', 'what does the claim status mean?');

                if ($scope.isClaim) {
                    $scope.StatusTypeToShow = 1;
                }
                else {
                    $scope.StatusTypeToShow = 2;
                }

                $scope.ShowStatusDescriptionDialog = true;
            }

            $scope.statusListOnChange = function () {
                if ($scope.isClaim && $scope.searchCriteria.Status != null && $scope.searchCriteria.Status.PORTAL_STATUS < 2) {
                    //If the status is Received or In Process, the Date Paid will be hidden. At that point, we'll clear the model.
                    $scope.searchCriteria.DATE_PAID_FROM = null;
                    $scope.searchCriteria.DATE_PAID_TO = null;
                }
                else if (!$scope.isClaim && $scope.searchCriteria.Status != null && $scope.searchCriteria.Status.PORTAL_STATUS == 0) {
                    //If the auth status is Pending, the Determination date will be hidden. At that point, we'll clear the model.
                    $scope.searchCriteria.DETERMINATION_DATE_FROM = null;
                    $scope.searchCriteria.DETERMINATION_DATE_TO = null;
                }
            }

            $scope.$watchCollection('[IsProcessingStatusSet, IsInsurerSet, IsLocationSet, IsProviderSet, IsFacilitySet, PerformAutoSearch]', function (n, o) {
                if (n[0] != null && n[1] != null && n[2] != null && n[3] != null && n[4] != null && n[5] != null && (n[0] != o[0] || n[1] != o[1] || n[2] != o[2] || n[3] != o[3] || n[4] != o[4] || n[5] != o[5])) {
                    $scope.performSearch();
                    $scope.PerformAutoSearch = false;
                }
            });

            $scope.$watch('AreStatusListLoaded', function (n, o) {
                if (n) {
                    $scope.statusList = $scope.StatusDescriptionLists[0].List;

                    $scope.autoSetProcessingStatus();

                    if (!$scope.isClaim) {
                        //The prepopulating is only for authorizations coming from welcome page.
                        var params = $location.search();
                        if (params != null) {
                            try {
                                if (params.searchType != '' && params.searchType != null) {
                                    if (parseInt(params.searchType) < $scope.statusList.length)
                                        $scope.searchCriteria.Status = $scope.statusList[parseInt(params.searchType)];

                                    if (params.searchType == "1") //determined, so set the date range to the last 30 days.
                                    {
                                        var today = new Date();
                                        var from = new Date(); from.setDate(from.getDate() - 30);
                                        
                                        $scope.searchCriteria.DETERMINATION_DATE_FROM = ('0' + (from.getMonth() + 1)).slice(-2) + '/' + ('0' + from.getDate()).slice(-2) + '/' + from.getFullYear();
                                        $scope.searchCriteria.DETERMINATION_DATE_TO = ('0' + (today.getMonth() + 1)).slice(-2) + '/' + ('0' + today.getDate()).slice(-2) + '/' + today.getFullYear();
                                    }
                                    $scope.PerformAutoSearch = true;
                                }
                            }
                            catch (e) {
                            }
                        }
                    }
                }
            });


            $scope.toggleSearchCriteriaPanel = function () {
                $scope.collapsePanels.isCollapsed = !$scope.collapsePanels.isCollapsed;
                $('#SearchCriteriaBody').collapse('toggle');
            }
        }]
    };
}]);

app.directive('wbxClaimAuthResults', ['$window','$location','$http', '$q', function ($window, $location, $http, $q) {
    return {
        restrict: 'E',
        templateUrl: '/Templates/ClaimAuthResults',
        scope: {
            statusList: '=',
            results: '=',
            isClaim: '=', /*true => Claims. false => Authorizations*/
            isSearch: '=', /*true => Search. false => Dashboard*/
            showResultsLoading: '=',
            searchText: '=',
            sessions: '='
        },
        controller: ['$scope', 'GoogleTagManagerService', function ($scope, googleTagManagerService) {
            $scope.init = function () {
                if (!$scope.isClaim) {
                     $scope.sortObject = {
                        sortColumn: 'AUTHORIZATION_NUMBER',
                        reverse: true
                    };
                }
                else {
                    $scope.sortObject = {
                        sortColumn: 'ENCOUNTER_ID',
                        reverse: false
                    };
                }

                $scope.historySortObject = {
                        sortColumn: 'ENCOUNTER_ID',
                        reverse: false
                };
            }

            $scope.sort = function (columnName) {

                if ($scope.sortObject.sortColumn != columnName)
                    $scope.sortObject.reverse = false;
                else
                    $scope.sortObject.reverse = !$scope.sortObject.reverse;

                $scope.sortObject.sortColumn = columnName;
            }

            $scope.sortHistory = function (columnName) {

                if ($scope.historySortObject.sortColumn != columnName)
                    $scope.historySortObject.reverse = false;
                else
                    $scope.historySortObject.reverse = !$scope.historySortObject.reverse;

                $scope.historySortObject.sortColumn = columnName;
            }



            $scope.viewClaim = function (claim) {

                var pageview = "view claim action";
                if ($location.absUrl().indexOf("/ClaimDashboard") > -1) {
                   pageview = "dashboard"
                }

                if ($location.absUrl().indexOf("/ClaimSearch") > -1) {
                   pageview = "claim search"
                }

                googleTagManagerService.setClickInfo('click', pageview, 'view claim icon', 'field_interaction', '', 'icon', 'view claim');

                var googletaginfo = {
                    "attribute1": pageview,
                    "attribute2": 'view claim icon',
                    "attribute3": 'field_interaction',
                    "attribute4": 'claim generated successfully',
                    "category": 'icon',
                    "label": 'view claim',
                }

                var sessionProperties = $scope.setSessionPropertiesForClaimReport(claim);

                $scope.openTab("/Areas/PWP/Reports/PortalClaimReport.aspx", sessionProperties, googletaginfo);
            }

            $scope.viewAuth = function (auth) {

                var pageview = "view auth action";
                if ($location.absUrl().indexOf("/ClaimDashboard") > -1) {
                   pageview = "dashboard"
                }

                if ($location.absUrl().indexOf("/ClaimSearch") > -1) {
                   pageview = "claim search"
                }

                googleTagManagerService.setClickInfo('click', pageview, 'view auth icon', 'field_interaction', '', 'icon', 'view auth');

                var googletaginfo = {
                    "attribute1": pageview,
                    "attribute2": 'view auth icon',
                    "attribute3": 'field_interaction',
                    "attribute4": 'authorization generated successfully',
                    "category": 'icon',
                    "label": 'view auth',
                }

                var sessionProperties = $scope.setSessionPropertiesForAuthReport(auth);

                $scope.openTab("/Areas/PWP/Reports/PortalAuthReport.aspx", sessionProperties, googletaginfo);
            }

            $scope.openDocument = function (url) {
                $window.open(url, '_blank', 'scrollbars=1,menubar=0,resizable=1,width=920,height=850');
            };

            $scope.setSessionPropertiesForClaimReport = function (claim) {
                var sessionProperties = [];
                var sessionProperty = {
                    SESSION_NAME: "REPORT_PORTAL_CLAIM_CLAIM_ID",
                    SESSION_VALUE: claim.CLAIM_ID
                }
                sessionProperties.push(sessionProperty);

                var sessionProperty = {
                    SESSION_NAME: "REPORT_PORTAL_CLAIM_SERVER_SOURCE",
                    SESSION_VALUE: claim.SERVER_SOURCE == undefined ? 3 : claim.SERVER_SOURCE
                }
                sessionProperties.push(sessionProperty);

                return sessionProperties;
            }

            $scope.setSessionPropertiesForAuthReport = function (auth) {
                var sessionProperties = [];
                var sessionProperty = {
                    SESSION_NAME: "REPORT_PORTAL_AUTH_AUTHORIZATION_ID",
                    SESSION_VALUE: auth.AUTHORIZATION_ID
                }
                sessionProperties.push(sessionProperty);

                var sessionProperty = {
                    SESSION_NAME: "REPORT_PORTAL_AUTH_DB_SOURCE",
                    SESSION_VALUE: auth.DB_SOURCE
                }
                sessionProperties.push(sessionProperty);

                return sessionProperties;
            }

            $scope.setSessionProperties = function (sessionProperties, googletaginfo) {
                var deferred = $q.defer();

                $http({
                    url: "/PortalWebSession/SetWebSessionProperties",
                    method: "PUT",
                    data: {
                        SESSION_PROPERTIES: sessionProperties
                    }
                }).then(function successCallback(response) {
                    if (!response.data.Status) {
                        console.error(response.data.Message);
                        console.error(response);
                        if ($scope.ExceptionDialogControl != null) {

                            if (googletaginfo != "notag") {
                                googleTagManagerService.setClickInfo('error', googletaginfo.attribute1, googletaginfo.attribute2, googletaginfo.attribute3, 'error with setting web session properties', googletaginfo.category, googletaginfo.label);
                            }

                            $scope.ExceptionDialogControl.showDialog("Error with setting web session properties.");
                        }
                        else {

                            if (googletaginfo != "notag") {

                                googleTagManagerService.setClickInfo('error', googletaginfo.attribute1, googletaginfo.attribute2, googletaginfo.attribute3, ((response.data.Message) ? response.data.Message.toLowerCase() : "an error has occurred"), googletaginfo.category, googletaginfo.label);
                            }

                            bootbox.alert(response.data.Message);
                        }
                        deferred.reject(false);
                    }
                    else {

                        if (googletaginfo != "notag") {
                            googleTagManagerService.setClickInfo('success', googletaginfo.attribute1, googletaginfo.attribute2, googletaginfo.attribute3, googletaginfo.attribute4, googletaginfo.category, googletaginfo.label);
                        }

                        deferred.resolve(true);
                    }
                }, function errorCallback(response) {

                    if (googletaginfo != "notag") {
                        googleTagManagerService.setClickInfo('error', googletaginfo.attribute1, googletaginfo.attribute2, googletaginfo.attribute3, 'error with setting web session properties', googletaginfo.category, googletaginfo.label);
                    }

                    console.error(response.data.Message);
                    console.error(response);
                    if ($scope.ExceptionDialogControl != null) {
                        $scope.ExceptionDialogControl.showDialog("Error with setting web session properties.");
                    }
                    else {
                        bootbox.alert(response.data.Message);
                    }
                    deferred.reject(false);
                });

                return deferred.promise;
            }

            $scope.openTab = function (url, sessionProperties, googletaginfo) {
                var randomno = Math.floor((Math.random() * 100) + 1);

                googletaginfo = googletaginfo || "notag";

                if (sessionProperties != null) {
                    var newWindow = $window.open('', 'PopUpWindow' + randomno, 'scrollbars=1,menubar=0,resizable=1,width=920,height=850');
                    
                    var timer = setInterval(function () {
                        if (newWindow.closed) {
                            clearInterval(timer);
                            googleTagManagerService.setClickInfo('click', 'claim dashboard', 'close window', 'close_window', '', 'button', 'close');
                        }
                    }, 1000);

                    var promise = $scope.setSessionProperties(sessionProperties, googletaginfo);
                    promise.then(function () {
                        newWindow.location = url;
                    }, function (data) {
                        // bad, do nothing
                    });
                }
                else {

                    if (googletaginfo != "notag") {
                        googleTagManagerService.setClickInfo('success', googletaginfo.attribute1, googletaginfo.attribute2, googletaginfo.attribute3, googletaginfo.attribute4, googletaginfo.category, googletaginfo.label);
                    }

                    window.open(url, 'PopUpWindow' + randomno, 'scrollbars=1,menubar=0,resizable=1,width=920,height=850');
                }
            }

            $scope.gotoClaimSearch = function () {

                googleTagManagerService.setClickInfo('click', 'dashboard', 'search historical claims button', 'field_interaction', '', 'button', 'search historical claims');

                var index = $location.absUrl().indexOf("/ClaimDashboard");
                $window.location.href = $location.absUrl().substr(0, index) + "/ClaimSearch";
            }

            $scope.startClaim = function (selectedItem) {

                googleTagManagerService.setClickInfo('click', 'dashboard', 'start claim button', 'field_interaction', '', 'button', 'start claim');

                $http({
                    url: "/Welcome/SetHomePageData",
                    method: "PUT",
                    data: {
                        AUTHORIZATION_NUMBER: selectedItem.AUTHORIZATION_NUMBER,
                        DATA_SOURCE: 8
                    }
                }).then(function successCallback(response) {
                    if (!response.data.Status) {
                        console.error(response.data.Message);
                        console.error(response);
                        if ($scope.ExceptionDialogControl != null) {

                            googleTagManagerService.setClickInfo('error', 'dashboard', 'start claim button', 'field_interaction', 'error in setting homepage data', 'button', 'start claim');

                            $scope.ExceptionDialogControl.showDialog("Error in setting homepage data.");
                        }
                        else {

                            googleTagManagerService.setClickInfo('error', 'dashboard', 'start claim button', 'field_interaction', ((response.data.Message) ? response.data.Message.toLowerCase() : "an error has occurred"), 'button', 'start claim');

                            bootbox.alert(response.data.Message);
                        }
                    }
                    else {

                        googleTagManagerService.setClickInfo('success', 'dashboard', 'start claim button', 'field_interaction', 'successful', 'button', 'start claim');

                        $window.location.href = '/PWP/Therapy/ClaimEntry';
                    }
                }, function errorCallback(response) {
                    console.error(response.data.Message);
                    console.error(response);
                    if ($scope.ExceptionDialogControl != null) {

                        googleTagManagerService.setClickInfo('error', 'dashboard', 'start claim button', 'field_interaction', 'error in setting homepage data', 'button', 'start claim');

                        $scope.ExceptionDialogControl.showDialog("Error in setting homepage data.");
                    }
                    else {

                        googleTagManagerService.setClickInfo('error', 'dashboard', 'start claim button', 'field_interaction', ((response.data.Message) ? response.data.Message.toLowerCase() : "an error has occurred"), 'button', 'start claim');
                            
                        bootbox.alert(response.data.Message);
                    }
                });
            }

            $scope.correctClaim = function (claim) {

                var pageview = "correct claim";
                if ($location.absUrl().indexOf("/ClaimDashboard") > -1) {
                   pageview = "dashboard"
                }

                if ($location.absUrl().indexOf("/ClaimSearch") > -1) {
                   pageview = "claim search"
                }

                $http({
                    url: "/Welcome/SetHomePageData",
                    method: "PUT",
                    data: {
                        ENCOUNTER_ID: claim.ENCOUNTER_ID, 
                        claimId: claim.CLAIM_ID
                    }
                }).then(function successCallback(response) {
                    if (!response.data.Status) {

                        googleTagManagerService.setClickInfo('error', pageview, 'correct claim icon', 'field_interaction', 'error in setting homepage data', 'icon', 'correct claim');

                        console.error(response.data.Message);
                        console.error(response);
                        if ($scope.ExceptionDialogControl != null) {
                            $scope.ExceptionDialogControl.showDialog("Error in setting homepage data.");
                        }
                        else {
                            bootbox.alert(response.data.Message);
                        }
                    }
                    else {

                        googleTagManagerService.setClickInfo('success', pageview, 'correct claim icon', 'field_interaction', 'successful', 'icon', 'correct claim');

                        var index = 0;
                        if ($location.absUrl().indexOf("/ClaimDashboard") > -1) {
                            index = $location.absUrl().indexOf("/ClaimDashboard");
                        }
                        else if ($location.absUrl().indexOf("/ClaimSearch") > -1) {
                            index = $location.absUrl().indexOf("/ClaimSearch");
                        }
                        if (index > -1)
                            $window.location.href = $location.absUrl().substr(0, index) + "/ClaimEntry";
                    }
                }, function errorCallback(response) {
                    console.error(response.data.Message);
                    console.error(response);
                    if ($scope.ExceptionDialogControl != null) {

                        googleTagManagerService.setClickInfo('error', pageview, 'correct claim icon', 'field_interaction', 'error in setting homepage data', 'icon', 'correct claim');

                        $scope.ExceptionDialogControl.showDialog("Error in setting homepage data.");
                    }
                    else {

                        googleTagManagerService.setClickInfo('error', pageview, 'correct claim icon', 'field_interaction', ((response.data.Message) ? response.data.Message.toLowerCase() : "an error has occurred"), 'icon', 'correct claim');

                        bootbox.alert(response.data.Message);
                    }
                });
            }

            $scope.viewClaimHistory = function (claim) {
             
                var pageview = "view claim history action";
                if ($location.absUrl().indexOf("/ClaimDashboard") > -1) {
                   pageview = "dashboard"
                }

                if ($location.absUrl().indexOf("/ClaimSearch") > -1) {
                   pageview = "claim search"
                }

                googleTagManagerService.setClickInfo('click', pageview, 'view claim history icon', 'field_interaction', '', 'icon', 'view claim history');

                if (claim.ORIGINAL_CLAIM_ID != null || claim.CLAIM_STATUS == 7 || claim.SERVICE_RESUBMITTED) {
                    $scope.claimHistorySelected = claim;
                    $scope.showClaimHistoryLoading = true;

                    // show dialog
                    $('#ClaimHistoryDialog').modal({
                        backdrop: 'static'
                    });
                    $('#ClaimHistoryDialog').modal('show');

                    // get claim history data
                    $http({
                        cache: false,
                        url: "/ClaimAuthSearch/GetClaimHistory",
                        method: "GET",
                        params: {
                            claimId: claim.CLAIM_ID
                        }
                    }).then(function successCallback(response) {
                        if (response.data != null) {
                            googleTagManagerService.setClickInfo('success', pageview, 'view claim history icon', 'field_interaction', 'view claim history successfully', 'icon', 'view claim history');

                            $scope.claimHistory = response.data;
                        }
                        else {
                            console.error(response.data.Message);
                            console.error(response);
                            if ($scope.ExceptionDialogControl != null) {

                                googleTagManagerService.setClickInfo('error', pageview, 'view claim history icon', 'field_interaction', "error in getting claim history.", 'icon', 'view claim history');

                                $scope.ExceptionDialogControl.showDialog("Error in getting claim history.");
                            }
                            else {

                                googleTagManagerService.setClickInfo('error', pageview, 'view claim history icon', 'field_interaction', ((response.data.Message) ? response.data.Message.toLowerCase() : "an error has occurred"), 'icon', 'view claim history');

                                bootbox.alert(response.data.Message);
                            }
                        }

                        $scope.showClaimHistoryLoading = false;

                    }, function errorCallback(response) {
                        console.error(response.data.Message);
                        console.error(response);
                        if ($scope.ExceptionDialogControl != null) {

                            googleTagManagerService.setClickInfo('error', pageview, 'view claim history icon', 'field_interaction', "error in getting claim history.", 'icon', 'view claim history');

                            $scope.ExceptionDialogControl.showDialog("Error in getting claim history.");
                        }
                        else {

                            googleTagManagerService.setClickInfo('error', pageview, 'view claim history icon', 'field_interaction', ((response.data.Message) ? response.data.Message.toLowerCase() : "an error has occurred"), 'icon', 'view claim history');

                            bootbox.alert(response.data.Message);
                        }
                        $scope.showClaimHistoryLoading = false;
                    });

                }
            }

            $scope.closeClaimHistory = function()
            {

                var pageview = "close view claim history";
                if ($location.absUrl().indexOf("/ClaimDashboard") > -1) {
                   pageview = "dashboard"
                }

                if ($location.absUrl().indexOf("/ClaimSearch") > -1) {
                   pageview = "claim search"
                }

                googleTagManagerService.setClickInfo('click', pageview, 'close view claim history modal', 'close_modal', '', 'button', 'close');

                $('#ClaimHistoryDialog').modal('hide');
            }

            $scope.correctClaimCheck = function(claim)
            {

                var pageview = "correct claim action";
                if ($location.absUrl().indexOf("/ClaimDashboard") > -1) {
                   pageview = "dashboard"
                }

                if ($location.absUrl().indexOf("/ClaimSearch") > -1) {
                   pageview = "claim search"
                }

                googleTagManagerService.setClickInfo('click', pageview, 'correct claim icon', 'field_interaction', '', 'icon', 'correct claim');   

                var rowversion = claim.ROWVERSION;
                $http({
                    cache: false,
                    url: "/ClaimAuthSearch/GetClaimRowVersion",
                    method: "GET",
                    params: {
                        claimId : claim.CLAIM_ID
                    }
                }).then(function successCallback(response) {
                    if (response.data != null && response.data[0] == rowversion) {
                            
                          googleTagManagerService.setClickInfo('error', pageview, 'correct claim icon', 'field_interaction', 'error in getting claim row version', 'icon', 'correct claim');

                          $scope.ConcurrencyCheckFailedDialogControl.showDialog(); 
                    }
                    else {

                        $scope.correctClaim(claim);
                    }
                }, function errorCallback(response) {
                    console.error(response.data.Message);
                    console.error(response);
                    if ($scope.ExceptionDialogControl != null) {

                        googleTagManagerService.setClickInfo('error', pageview, 'correct claim icon', 'field_interaction', 'error in getting claim row version', 'icon', 'correct claim');

                        $scope.ExceptionDialogControl.showDialog("Error in getting claim row version.");
                    }
                    else {

                        googleTagManagerService.setClickInfo('error', pageview, 'correct claim icon', 'field_interaction', ((response.data.Message) ? response.data.Message.toLowerCase() : "an error has occurred"), 'icon', 'correct claim');

                        bootbox.alert(response.data.Message);
                    }
                    $scope.ConcurrencyCheckFailedDialogControl.showDialog(); 
                });
            }

            $scope.gotoClaimSearchPage = function () {
                    $scope.ConcurrencyCheckFailedDialogControl.hideDialog(); 
                }

            $scope.showInstantEOB = function (documentId, preClaimId) {

                $http({
                    url: "/Dental/ViewInstantEOB",
                    method: "POST",
                    data: {
                        DOCUMENT_ID: documentId,
                        PRECLAIM_ID: preClaimId,
                        IS_LOG: true
                    }
                }).then(function successCallback(response) {
                    if (!response.data.Status) {
                        console.error(response.data.Message);
                        console.error(response);
                        $scope.ExceptionDialogControl.showDialog("Unexpected error with showing Instant EOB.");
                    } else {
                        $scope.openTab(response.data.Data.Url);
                    }
                }, function errorCallback(response) {
                    console.error(response.data.Message);
                    console.error(response);
                    $scope.ExceptionDialogControl.showDialog("Unexpected error with showing Instant EOB.");
                });
            }
        }]
    };

}]);

app.directive('wbxStatusDescriptionDialog', ['$http','$window','$timeout', '$location', function ($http, $window, $timeout, $location) {
    return {
        restrict: 'E',
        templateUrl: '/Templates/StatusDescriptionDialog',
        scope: {
            statusesToLoad: '=', // This is an array of objects. Each object will have the portal processing type (PORTAL_PROCESSING_TYPE) we want to load and the title (TITLE) and a list of colors (ColorList:{Green,Gold,Red}).
            statusDescriptionLists: '=', //This is an array of status description lists. The order would depend on the order in statusesToLoad
            statusTypeToShow: '=', //This is to indicate which status list to show
            showDialog: '=', //This is an event to trigger the display of the dialog
            areStatusListLoaded: '=', //This is to indicate if all the lists are done loading
            sortDescending: '=?'
        },
        controller: ['$scope', 'GoogleTagManagerService' , function ($scope, googleTagManagerService) {
            $scope.sortDescending = $scope.sortDescending || false;

            $scope.getStatusList = function (statusToLoad) {
                $http({
                    method: 'GET',
                    url: '/PortalDropList/GetPortalProcessingStatuses',
                    params: {
                        PORTAL_PROCESSING_TYPE: statusToLoad.PORTAL_PROCESSING_TYPE
                    }
                }).then(function successCallback(response) {
                    if (response.data.length > 0) {

                        if (statusToLoad.ColorList != null){
                            if (statusToLoad.ColorList.Green != null){
                                angular.forEach(statusToLoad.ColorList.Green, function (green) {
                                    angular.forEach(response.data, function (status) {
                                        if (status.PORTAL_STATUS == green) {
                                            status.IsGreen = true;
                                        }
                                    });
                                });
                            }
                            if (statusToLoad.ColorList.Gold != null) {
                                angular.forEach(statusToLoad.ColorList.Gold, function (gold) {
                                    angular.forEach(response.data, function (status) {
                                        if (status.PORTAL_STATUS == gold) {
                                            status.IsGold = true;
                                        }
                                    });
                                });
                            }
                            if (statusToLoad.ColorList.Red != null) {
                                angular.forEach(statusToLoad.ColorList.Red, function (red) {
                                    angular.forEach(response.data, function (status) {
                                        if (status.PORTAL_STATUS == red) {
                                            status.IsRed = true;
                                        }
                                    });
                                });
                            }
                        }

                        if ($scope.statusDescriptionLists == null) {
                            $scope.statusDescriptionLists = [];
                        }

                        $scope.statusDescriptionLists.push(
                            {
                                TITLE: statusToLoad.TITLE,
                                PORTAL_PROCESSING_TYPE: statusToLoad.PORTAL_PROCESSING_TYPE,
                                List: response.data
                            }
                        );
                    }
                    
                    $scope.StatusListLoaded = true;
                }, function errorCallback(response) {
                    console.error(response.data.Message);
                    console.error(response);
                    if ($scope.ExceptionDialogControl != null) {
                        $scope.ExceptionDialogControl.showDialog("Error in getting portal processing statuses.");
                    }
                    else {
                        bootbox.alert(response.data.Message);
                    }
                });
            }

            $scope.showStatusDescription = function () {
                $('#StatusDescriptionDialog').modal({
                    backdrop: 'static'
                })
                $('#StatusDescriptionDialog').modal('show');
            }

            $scope.closeStatusDescriptionDialog = function () {

                var pageview = "claim status modal";
                if ($location.absUrl().indexOf("/ClaimDashboard") > -1) {
                   pageview = "dashboard"
                }

                if ($location.absUrl().indexOf("/ClaimSearch") > -1) {
                   pageview = "claim search"
                }

                googleTagManagerService.setClickInfo('click', pageview, 'close claim status icon', 'close_modal', '', 'icon', 'close icon');
                $('#StatusDescriptionDialog').modal('hide');
            }

            $scope.$watchCollection('statusesToLoad', function (n, o) {
                if (n != null && n.length > 0) {
                    angular.forEach($scope.statusesToLoad, function (status) {
                        $scope.getStatusList(status);
                    });
                }
            });

            $scope.$watch('StatusListLoaded', function (n, o) {
                if (n) {
                    if ($scope.statusDescriptionLists != null && $scope.statusesToLoad != null && $scope.statusDescriptionLists.length == $scope.statusesToLoad.length) {
                        $scope.areStatusListLoaded = true;
                    }

                    $scope.StatusListLoaded = false;
                }
            });

            $scope.$watchCollection('[showDialog,areStatusListLoaded]', function (n, o) {
                if (n[0] && n[1]) {
                    $scope.Status = _.findWhere($scope.statusDescriptionLists, { PORTAL_PROCESSING_TYPE: $scope.statusTypeToShow });
                    $scope.showStatusDescription();

                    $scope.showDialog = false;
                }
            });
        }]
    };
}]);

app.directive('wbxCapApplicationDetails', ['$window', '$http', function ($window, $http) {
    return {
        restrict: 'E',
        templateUrl: '/Templates/CAPApplicationDetails',
        scope: {
            providerId: '=',
            credentialingApplicationId: '=',
            showDialog: '=',
            hideStatus: '='
        },
        controller: ['$scope', function ($scope) {
            $scope.init = function () {
                $scope.getStatuses();
            }

            $scope.showApplicationDetails = function () {
                $('#ApplicationDetailsTab a:first').tab('show');

                $('#application-details').modal({
                    backdrop: 'static'
                })
                $('#application-details').modal('show');
            }

            $scope.closeApplicationDetails = function () {
                $('#application-details').modal('hide');
                $scope.ShowDialogContent = false;
                $scope.ErrorLoadingOverviewInfo = false;
            }

            $scope.getStatuses = function () {
                $http({
                    method: 'GET',
                    url: '/PortalDropList/GetPortalProcessingStatuses',
                    params: {
                        PORTAL_PROCESSING_TYPE: 5 //Download
                    }
                }).then(function (result) {
                    $scope.DownloadStatusList = result.data;
                    $scope.StatusListLoaded = true;
                }, function (data, status, headers, config) {
                    bootbox.alert(data);
                });

                $http({
                    method: 'GET',
                    url: '/PortalDropList/GetPortalProcessingStatuses',
                    params: {
                        PORTAL_PROCESSING_TYPE: 6 //Subscription
                    }
                }).then(function (result) {
                    $scope.SubscriptionStatusList = result.data;
                    $scope.SubscriptionListLoaded = true;
                }, function (data, status, headers, config) {
                    bootbox.alert(data);
                });
            }

            $scope.getProviderInfo = function () {
                $http({
                    cache: false,
                    url: "/CAP/ApplicationDetails/GetProviderInfo",
                    method: "GET",
                    params: {
                        PROVIDER_ID: $scope.providerId
                    }
                }).then(function (data) {
                    data = data.data;
                    if (data.error)
                        bootbox.alert(data.message);
                    else {
                        if (data != null && data.length != 0) {
                            $scope.ProviderInfo = data;
                            $scope.ProviderInfoLoaded = true;
                        }
                    }
                }, function (data, status, headers, config) {
                    bootbox.alert(data);
                });
            }

            $scope.getOverviewInfo = function () {
                $scope.ShowDetailsDialogLoading = true;

                $http({
                    cache: false,
                    url: "/CAP/ApplicationDetails/GetOverviewInfo",
                    method: "GET",
                    params: {
                        CREDENTIALING_APPLICATION_ID: $scope.credentialingApplicationId
                    }
                }).then(function (data) {
                    data = data.data;
                    $scope.ShowDetailsDialogLoading = false;
                    if (data.Status == false) {
                        $scope.ErrorLoadingOverviewInfo = true;
                    }
                    else {
                        $scope.OverviewDetails = data;

                        $scope.OverviewDetails.PERSONAL_INFO_UPDATED = ($scope.OverviewDetails.SECTIONS_UPDATED & 15) > 0 ? true : false;
                        $scope.OverviewDetails.PRACTICE_INFO_UPDATED = ($scope.OverviewDetails.SECTIONS_UPDATED & 16) > 0 ? true : false;
                        $scope.OverviewDetails.STATE_DOCUMENTS_UPDATED = ($scope.OverviewDetails.SECTIONS_UPDATED & 32) > 0 ? true : false;
                        $scope.OverviewDetails.ANESTHESIA_DOCUMENTS_UPDATED = ($scope.OverviewDetails.SECTIONS_UPDATED & 64) > 0 ? true : false;
                        $scope.OverviewDetails.DEA_DOCUMENTS_UPDATED = ($scope.OverviewDetails.SECTIONS_UPDATED & 128) > 0 ? true : false;
                        $scope.OverviewDetails.CDS_DOCUMENTS_UPDATED = ($scope.OverviewDetails.SECTIONS_UPDATED & 256) > 0 ? true : false;
                        $scope.OverviewDetails.MEDICARE_UPDATED = ($scope.OverviewDetails.SECTIONS_UPDATED & 512) > 0 ? true : false;
                        $scope.OverviewDetails.MEDICAID_UPDATED = ($scope.OverviewDetails.SECTIONS_UPDATED & 1024) > 0 ? true : false;
                        $scope.OverviewDetails.BLS_UPDATED = ($scope.OverviewDetails.SECTIONS_UPDATED & 2048) > 0 ? true : false;
                        $scope.OverviewDetails.ACLS_UPDATED = ($scope.OverviewDetails.SECTIONS_UPDATED & 4096) > 0 ? true : false;
                        $scope.OverviewDetails.DEGREE_UPDATED = ($scope.OverviewDetails.SECTIONS_UPDATED & 8192) > 0 ? true : false;
                        $scope.OverviewDetails.RESIDENCY_INTERNSHIP_UPDATED = ($scope.OverviewDetails.SECTIONS_UPDATED & 16384) > 0 ? true : false;
                        $scope.OverviewDetails.BOARD_CERTIFICATIONS_UPDATED = ($scope.OverviewDetails.SECTIONS_UPDATED & 32768) > 0 ? true : false;
                        //$scope.OverviewDetails.NDBE_UPDATED = ($scope.OverviewDetails.SECTIONS_UPDATED & 65536) > 0 ? true : false;
                        $scope.OverviewDetails.HOSPITAL_AFFILIATIONS_UPDATED = ($scope.OverviewDetails.SECTIONS_UPDATED & 131072) > 0 ? true : false;
                        $scope.OverviewDetails.PROFESSIONAL_INSURANCE_UPDATED = ($scope.OverviewDetails.SECTIONS_UPDATED & 262144) > 0 ? true : false;
                        $scope.OverviewDetails.ATTACHMENTS_DOO_DOCUMENTS_UPDATED = ($scope.OverviewDetails.SECTIONS_UPDATED & 4194304) > 0 ? true : false;
                        $scope.OverviewDetails.ATTACHMENTS_OTHER_DOCUMENTS_UPDATED = ($scope.OverviewDetails.SECTIONS_UPDATED & 8388608) > 0 ? true : false;
                      

                        if (!$scope.hideStatus != null) {
                            if ($scope.hideStatus == 1) {
                                $scope.OverviewDetails.APPLICATION_STATUS = -1;
                            }
                        }

                        $scope.OverviewInfoLoaded = true;
                    }

                }, function (data, status, headers, config) {
                    bootbox.alert(data);
                });
            }

           
         

            $scope.getLocationsList = function () {
                $scope.ShowLoadingLocationList = true;
                $http({
                    cache: false,
                    url: "/CAP/ApplicationDetails/GetLocationsList",
                    method: "GET",
                    params: {
                        CREDENTIALING_APPLICATION_ID: $scope.credentialingApplicationId
                    }
                }).then(function (data) {
                    $scope.LocationsList = data.data;

                    $scope.LocationsListLoaded = true;
                    $scope.ShowLoadingLocationList = false;
                }, function (data, status, headers, config) {
                    $scope.ShowLoadingLocationList = false;
                    bootbox.alert(data);
                });
            }

            $scope.getOtherInformationInfo = function () {
                $scope.ShowLoadingOtherInfo = true;
                $http({
                    cache: false,
                    url: "/CAP/ApplicationDetails/GetOtherInformationInfo",
                    method: "GET",
                    params: {
                        CREDENTIALING_APPLICATION_ID: $scope.credentialingApplicationId
                    }
                }).then(function (data) {
                    $scope.OtherInformationDetails = data.data;
                    $scope.OtherInformationDetailsLoaded = true;
                    $scope.ShowLoadingOtherInfo = false;
                }, function (data, status, headers, config) {
                    $scope.ShowLoadingOtherInfo = false;
                    bootbox.alert(data);
                });
            }
            
            //This is to generate the status name. It has to wait for the status list to be loaded as well as the overview details.
            $scope.$watchCollection('[StatusListLoaded, OverviewInfoLoaded]', function (n, o) {
                if (n[0] != null && n[1] != null && (n[0] != o[0] || n[1] != o[1])) {
                    $scope.OverviewDetails.STATUS_NAME = _.findWhere($scope.DownloadStatusList, { PORTAL_STATUS: $scope.OverviewDetails.APPLICATION_STATUS }).NAME;
                }
            });

            $scope.$watchCollection('[SubscriptionListLoaded, OverviewInfoLoaded]', function (n, o) {
                if (n[0] != null && n[1] != null && (n[0] != o[0] || n[1] != o[1])) {
                    var subscriptionPortalStatus = $scope.OverviewDetails.SUBSCRIPTION_ACTIVE_FLAG ? 1 : 0;
                    $scope.OverviewDetails.SUBSCRIPTION_STATUS_NAME = _.findWhere($scope.SubscriptionStatusList, { PORTAL_STATUS: subscriptionPortalStatus }).NAME;
                }
            });


         
        
       

            $scope.$watch('showDialog', function (n, o) {
                if (n) {
                    $scope.showApplicationDetails();

                    $scope.getProviderInfo();

                    //Load tab 1
                    $scope.getOverviewInfo();
                  
                    $scope.showDialog = false;

                }
            });
            
            $scope.$watchCollection('[ProviderInfoLoaded, OverviewInfoLoaded]', function (n, o) {
                if (n[0] && n[1]) {
                    $scope.ShowDialogContent = true;

                    //Load tab 2 and tab 3
                    $scope.getLocationsList();
                    $scope.getOtherInformationInfo();

                    $scope.ProviderInfoLoaded = false;
                    $scope.OverviewInfoLoaded = false;
                }
            });
        }]
    };
}]);

app.directive('wbxCapApplicationDownload', ['$window', '$http', '$timeout', 'WBXBatchAppCountService','bowser', function ($window, $http, $timeout, WBXBatchAppCountService, bowser) {
    return {
        restrict: 'E',
        templateUrl: '/Templates/CAPApplicationDownload',
        scope: {
            selectedProvider: '=',
            displayPurchase: '=',
            downloadNow: '=',
            addToBatch: '=',
            removeFromBatch: '=',
            downloadStatus: '=?',
            packageType: '='
        },
        controller: ['$scope', function ($scope) {
            $scope.init = function () {
            }

            $scope.showPurchaseDialog = function () {
                $('#confirm-purchase').modal({
                    backdrop: 'static'
                })
                $('#confirm-purchase').modal('show');
            }

            $scope.cancelConfirmPurchase = function () {
                $('#confirm-purchase').modal('hide');
            }

            $scope.showFailedDownloadDialog = function () {
                $('#failed-download').modal({
                    backdrop: 'static'
                })
                $('#failed-download').modal('show');
            }

            $scope.closeFailedDownload = function () {
                $('#failed-download').modal('hide');
            }

            $scope.showIncompleteDownloadDialog = function () {
                $('#incomplete-download').modal({
                    backdrop: 'static'
                })
                $('#incomplete-download').modal('show');
            }

            $scope.closeIncompleteDownloadDialog = function () {
                $('#incomplete-download').modal('hide');
            }


            $scope.subscribe = function () {
                $('#confirm-purchase').modal('hide');

                $http({
                    url: "/CAP/Download/Subscribe",
                    method: "PUT",
                    data: {
                        providerId: $scope.selectedProvider.PROVIDER_ID,
                    }
                }).then(function (data) {
                    data = data.data;
                    if (!data.Status) {
                        bootbox.alert(data.Message);
                    }
                    else {
                        $scope.selectedProvider.IS_SUBSCRIPTION_EXPIRED = false;
                        var currentdate = new Date();
                        $scope.selectedProvider.SUBSCRIPTION_START_DATE = currentdate.getDate() + "/" + (currentdate.getMonth() + 1) + "/" + currentdate.getFullYear();
                        $scope.selectedProvider.SUBSCRIPTION_STATUS = 1;

                        $scope.clearBanners();
                        $scope.ShowSubscriptionActivatedBanner = true;

                        $timeout.cancel($scope.SubscribeTimer);
                        //Close the info banner automatically in 10 seconds
                        $scope.SubscribeTimer = $timeout(function () {
                            $scope.ShowSubscriptionActivatedBanner = false;
                        }, 10000);
                    }
                }, function (data, status, headers, config) {
                    bootbox.alert(data);
                });
            }

            $scope.closeSubscriptionActivatedBanner = function () {
                $scope.ShowSubscriptionActivatedBanner = false;
            }

            $scope.closeDownloadNowInitiatedBanner = function () {
                $scope.ShowDownloadNowInitiatedBanner = false;
            }

            $scope.closeAppAddedToBatchBanner = function () {
                $scope.ShowAppAddedToBatchBanner = false;
            }

            $scope.closeAppRemovedFromBatchBanner = function () {
                $scope.ShowAppRemovedFromBatchBanner = false;
            }

            $scope.clearBanners = function () {
                $scope.ShowSubscriptionActivatedBanner = false;
                $scope.ShowDownloadNowInitiatedBanner = false;
                $scope.ShowAppAddedToBatchBanner = false;
                $scope.ShowAppRemovedFromBatchBanner = false;
            }

            $scope.$watch('displayPurchase', function (n, o) {
                if (n) {
                    $scope.showPurchaseDialog();

                    $scope.displayPurchase = false;
                }
            });

            $scope.$watch('downloadNow', function (n, o) {

                if (n) {
                    $scope.clearBanners();
                    $scope.ShowDownloadNowInitiatedBanner = true;

                    $timeout.cancel($scope.DownloadNowTimer);
                    //Close the info banner automatically in 10 seconds
                    $scope.DownloadNowTimer = $timeout(function () {
                        $scope.ShowDownloadNowInitiatedBanner = false;
                    }, 10000);

                    if (bowser.safari) {
                        if ($scope.selectedProvider != null)
                            window.open("/CAP/Download/Download?appId=" + $scope.selectedProvider.PROVIDER_CREDENTIALING_APPLICATION_ID + "&packageType=" + $scope.packageType, '_self', '');
                        else {
                            window.open("/CAP/Download/Download?packageType=" + $scope.packageType, '_self', '');
                            $scope.downloadStatus = "200";
                        }
                    }
                    else {
                        try {
                            var isFileSaverSupported = !!new Blob;
                            $http({
                                method: 'GET',
                                url: '/CAP/Download/Download',
                                responseType: 'arraybuffer',
                                params: {
                                    providerId: $scope.selectedProvider != null ? $scope.selectedProvider.PROVIDER_ID : null,
                                    appId: $scope.selectedProvider != null ? $scope.selectedProvider.PROVIDER_CREDENTIALING_APPLICATION_ID : null,
                                    packageType: $scope.packageType
                                }
                            }).then(function successCallback(response) {
                                //Get the content type
                                var type = response.headers('content-type');

                                //Get the file name
                                var contentDisposition = response.headers('content-disposition');
                                var indexFileName = contentDisposition.indexOf('filename=');
                                var indexName = indexFileName + 9;
                                var fileName = contentDisposition.substr(indexName);

                                var file = new Blob([response.data], {
                                    type: type
                                });

                                saveAs(file, fileName);

                                if (response.status == "206")
                                    $scope.showIncompleteDownloadDialog();
                                else if ($scope.selectedProvider != null) {
                                    //When the download is successful, set the download status to application current (3)
                                    $scope.selectedProvider.DOWNLOAD_STATUS = 3;
                                }

                                $scope.downloadStatus = response.status;
                            }, function errorCallback(response) {
                                $scope.downloadStatus = response.status;
                                $scope.showFailedDownloadDialog();
                            });
                        } catch (e) {
                            if ($scope.selectedProvider != null)
                                window.open("/CAP/Download/Download?appId=" + $scope.selectedProvider.PROVIDER_CREDENTIALING_APPLICATION_ID + "&packageType=" + $scope.packageType, '_self', '');
                            else
                                window.open("/CAP/Download/Download?packageType=" + $scope.packageType, '_self', '');
                        }
                    }

                    $scope.downloadNow = false;
                }

            });

            $scope.$watch('addToBatch', function (n, o) {
                if (n) {
                        $http({
                            url: "/CAP/Download/AddToBatch",
                            method: "PUT",
                            data: {
                                providerId: $scope.selectedProvider.PROVIDER_ID,
                                appId: $scope.selectedProvider.PROVIDER_CREDENTIALING_APPLICATION_ID
                            }
                        }).then(function (data) {
                            data = data.data;
                            if (!data.Status) {
                                bootbox.alert(data.Message);
                            }
                            else {
                                //Update batch count
                                WBXBatchAppCountService.addApplication();
                                $scope.selectedProvider.IS_IN_BATCH = true;

                                $scope.clearBanners();
                                $scope.ShowAppAddedToBatchBanner = true;

                                $timeout.cancel($scope.AppAddedToBatchTimer);
                                //Close the info banner automatically in 10 seconds
                                $scope.AppAddedToBatchTimer = $timeout(function () {
                                    $scope.ShowAppAddedToBatchBanner = false;
                                }, 10000);
                            }
                        }, function (data, status, headers, config) {
                            bootbox.alert(data);
                        });

                    $scope.addToBatch = false;
                }
            });

            $scope.$watch('removeFromBatch', function (n, o) {
                if (n) {
                    $http({
                        url: "/CAP/Download/RemoveFromBatch",
                        method: "PUT",
                        data: {
                            appId: $scope.selectedProvider.PROVIDER_CREDENTIALING_APPLICATION_ID
                        }
                    }).then(function (data) {
                        data = data.data;
                        if (!data.Status) {
                            bootbox.alert(data.Message);
                        }
                        else {
                            //Update batch count
                            $scope.selectedProvider.IS_IN_BATCH = false;
                            WBXBatchAppCountService.delApplication();

                            $scope.clearBanners();
                            $scope.ShowAppRemovedFromBatchBanner = true;

                            $timeout.cancel($scope.AppRemovedFromBatchTimer);
                            //Close the info banner automatically in 10 seconds
                            $scope.AppRemovedFromBatchTimer = $timeout(function () {
                                $scope.ShowAppRemovedFromBatchBanner = false;
                            }, 10000);
                        }
                    }, function (data, status, headers, config) {
                        bootbox.alert(data);
                    });

                    $scope.removeFromBatch = false;
                }
            });
        }]
    };
}]);

app.directive('wbxModalDialog', ['$parse', '$compile', '$timeout', '$filter', function ($parse, $compile, $timeout, $filter) {
    return {
        restrict: 'E',
        templateUrl: '/Templates/ModalDialog',
        transclude: true,
        scope: {
            control: '=',
            headerText: '=',
            subHeaderText: '=?', //sub header text
            bodyTextArray: '=', //List of basic text to display
            buttonsArray: '<?', //This is a list of buttons to display
            btnWidth: '=?', //This is so that all the buttons have the same size.
            isEscDisabled: '=?', //This is to remove the X icon on the top right and not allowing esc key to be used
            cancelOnClick: '&?'
        },
        controller: ['$scope', function ($scope) {
            $scope.XButtonxOnClick = function () {
                $scope.control.hideDialog();
                $scope.cancelOnClick();
            }
        }],
        link: function (scope, element, attr, ctrl, $transclude) {

            $transclude(function (clone) {
                /*
                if (clone.length == 0 || (clone.length == 1 && !_.isUndefined(clone[0].context) && clone[0].context.textContent.replace(/^\s+|\s+$/g, '').length == 0)) {
                    scope.HasTransclude = false;
                }
                else {
                    scope.HasTransclude = true;
                }*/

                scope.HasTransclude = true;
            });

            //Set Aria  label
            scope.AriaLabel = attr.ariaLabelledby
            //Set Modal Id
            scope.ModalId = attr.name != null ? attr.name.replace(/ /g, "").replace(/-/g, "") : "GenericModalDialog";
            //Set Size
            scope.Size = attr.size;

            //Set Control
            scope.control = scope.control || {};
            scope.control.showDialog = function () {

                if (scope.isEscDisabled) {
                    $('#' + scope.ModalId).modal({
                        backdrop: 'static',
                        keyboard: false //Disabling esc key
                    });
                }
                else {
                    $('#' + scope.ModalId).modal({
                        backdrop: 'static'
                    });
                }

                $('#' + scope.ModalId).modal('show');
            };

            scope.control.hideDialog = function () {
                $('#' + scope.ModalId).modal('hide');
            };

            var buttonCount = 0;

            $timeout(function () {
                if (scope.buttonsArray != null) {
                    //Order the array so that the secondary buttons are first (left on the dialog).
                    var orderedButtonsArray = $filter('orderBy')(scope.buttonsArray, 'IsPrimary');

                    if (orderedButtonsArray != null) {
                        orderedButtonsArray.forEach(function (button) {

                            //Specify the width so all buttons have the same width. Also add margin-left on buttons that are not the most left
                            var buttonName = button.Text != null ? button.Text.replace(/ /g, "").replace(/-/g, "") : "GenericButton";

                            //Specify minimum width of 60px so that no button will be too small;
                            var style = "";
                            style += "style=\"min-width:60px";
                            if ((scope.btnWidth != null && scope.btnWidth != "")) {
                                style += ";width:" + scope.btnWidth;
                            }

                            if (buttonCount > 0) {
                                style += ";margin-left:10px";
                            }

                            style += "\"";

                            //Differentiate primary and seconary color.
                            var buttonColor = "btn-default";
                            if (button.IsPrimary) {
                                buttonColor = "btn-primary";
                            }

                            var functionName = "";
                            if (button.OnClick == null || button.OnClick == "") {
                                //If button OnClick isn't provided, we'll create a default one
                                button.OnClick = scope.ModalId + buttonName + buttonCount;
                                functionName = button.OnClick;
                                buttonCount++;
                            }
                            else {
                                functionName = '$parent.' + button.OnClick;
                            }

                            var btnhtml = '<button type="button" class="btn ' + buttonColor + ' btn-xs"' + style + ' id="' + scope.ModalId + buttonName + 'Button" ng-click="' + functionName + '()">' + button.Text + '</button>';
                            var temp = $compile(btnhtml)(scope);
                            
                            angular.element(document.getElementById(scope.ModalId + "ButtonsPlaceHolder")).append(temp);

                            if (button.OnClick) {
                                var fn = functionName + "()";

                                //get a reference to the function defined in the scope
                                var getParentMethod = $parse(fn);

                                // For example if the markup is -- <button on-click="test(arg1, arg2)"
                                // arg1, arg2 needs to be evaluated in the scope
                                // As isolateScope breaks the inheritance chain, we need to pass element.scope() to the parser function to access the arg1, arg2 properties from controllers scope

                                // define a method in the scope with the value of button.OnClick (eg, clickedx)
                                scope[functionName] = function (locals) {
                                    if (button.IsClosingDialog) {
                                        scope.control.hideDialog();
                                    }
                                    // when scope.clickedx is executed, execute the method defined in the controller. 
                                    return getParentMethod(element.scope(), locals);
                                }
                            }
                        });
                    }
                }
            });
        }
    };
}]);

app.directive('wbxExceptionDialog', ['$parse', '$compile', '$timeout', '$filter', function ($parse, $compile, $timeout, $filter) {
    return {
        restrict: 'E',
        templateUrl: '/Templates/ModalDialog',
        scope: {
            control: '='
        },
        link: function (scope, element, attr) {
            scope.AriaLabel = "Error";
            scope.ModalId = "ErrorDialog";
            scope.headerText = "Error";

            //Set Control
            scope.control = scope.control || {};
            scope.control.showDialog = function (message) {
                scope.bodyTextArray = [message];
                $('#' + scope.ModalId).modal({
                    backdrop: 'static'
                });

                $('#' + scope.ModalId).modal('show');
            };

            scope.control.hideDialog = function () {
                $('#' + scope.ModalId).modal('hide');
            };

            $timeout(function () {
                var btnhtml = '<button type="button" class="btn btn-primary btn-xs" style="width:60px" id="ErrorOKButton" ng-click="ErrorOKButton()">OK</button>';
                var temp = $compile(btnhtml)(scope);

                angular.element(document.getElementById(scope.ModalId + "ButtonsPlaceHolder")).append(temp);

                scope.ErrorOKButton = function (locals) {
                    scope.control.hideDialog();
                }
            });
        }
    };
}]);

app.directive('wbxVerificationStatus', ['$http', function ($http) {
    return {
        restrict: 'E',
        templateUrl: '/Templates/VerificationStatus',
        scope: {
            name: '@',                //This is to have unique id for the denial code dialog
            status: '=',            //VERIFICATION_STATUS
            verifiedBy: '=?',       //This is only relevant for VERIFICATION_STATUS == 1 (Verified)
            validationDate: '=?',   //This is only relevant for VERIFICATION_STATUS == 1 (Verified)
            dueDate: '=?',          //This is only relevant for VERIFICATION_STATUS == 3 (Due)
            verificationId: '=?',   //This is only relevant for VERIFICATION_STATUS == 4 (Denied)
            daysToExpire: '=?',     //This is only relevant for VERIFICATION_STATUS == 5 (Past Due)
            expiredDate: '=?',      //This is only relevant for VERIFICATION_STATUS == 6 (Expired)
            statusList: '=',        //List for Verification Status
            icons: '='
        },
        controller: ['$scope', function ($scope) {
            $scope.StatusObject = {
                VERIFICATION_STATUS_NAME: null,
                VERIFICATION_STATUS_COLOR: {
                    IsRed: false,
                    IsGreen: false,
                    IsGold: false
                },
                SingleMargin: null,
                Tooltip: null
            };

            //Set the appropriate status name, icon, etc when both statusList and status are set
            $scope.$watchCollection('[statusList, status]', function (n, o) {
                if (n[0] != null) {
                    if ($scope.status == null) {
                        $scope.status = 0;
                    }

                    if ($scope.status == 0) {
                        $scope.StatusObject.Tooltip = "Verification not required.";
                        $scope.TextPosition = {
                            'vertical-align': 'text-top'
                        };
                    }
                    else if ($scope.status == 1) {
                        $scope.StatusObject.Tooltip = "Verified by " + $scope.verifiedBy + " on " + $scope.validationDate + ".";
                        $scope.TextPosition = {
                            'vertical-align': 'text-bottom'
                        };
                    }
                    else if ($scope.status == 2) {
                        $scope.StatusObject.Tooltip = "Pending administrator approval.";
                        $scope.TextPosition = {
                            'vertical-align': 'text-bottom'
                        };
                    }
                    else if ($scope.status == 3) {
                        $scope.StatusObject.Tooltip = "Due on " + $scope.dueDate + ".";
                        $scope.TextPosition = {
                            'vertical-align': 'text-top'
                            };
                    }
                    else if ($scope.status == 4) {
                        $scope.StatusObject.Tooltip = "Denied - See notes for more information.";
                        $scope.TextPosition = {
                            'vertical-align': 'text-top'
                        };
                    }
                    else if ($scope.status == 5) {
                        $scope.StatusObject.Tooltip = "Remove from directory in " + $scope.daysToExpire + " days.";
                        $scope.TextPosition = {
                            'vertical-align': 'text-top'
                        };
                    }
                    else if ($scope.status == 6) {
                        $scope.StatusObject.Tooltip = "Expired on " + $scope.expiredDate + ".";
                        //Special margin for Expired status due to icon a bit wider
                        $scope.StatusObject.SingleMargin = { 'margin-right': '1px' };
                        $scope.TextPosition = {
                            'vertical-align': 'text-top'
                        };
                    }

                    var selectedStatus = _.findWhere($scope.statusList, {
                        PORTAL_STATUS: $scope.status
                    });

                    $scope.StatusObject.ICON = selectedStatus.ICON;
                    $scope.StatusObject.VERIFICATION_STATUS_NAME = selectedStatus.NAME;
                    $scope.StatusObject.VERIFICATION_STATUS_COLOR.IsGreen = selectedStatus.IsGreen;
                    $scope.StatusObject.VERIFICATION_STATUS_COLOR.IsGold = selectedStatus.IsGold;
                    $scope.StatusObject.VERIFICATION_STATUS_COLOR.IsRed = selectedStatus.IsRed;
                }
            });
            
            $scope.showDenialNotes = function (verificationId) {
                $scope.LoadingDenialInfo = true;
                
                $http({
                    method: 'GET',
                    url: '/EntityManagement/GetDenialInfo',
                    params: {
                        VERIFICATION_ID: verificationId
                    }
                }).then(function successCallback(response) {
                    if (response.data != null) {
                        $scope.DenialInfo = {
                            REASON: response.data.DESCRIPTION,
                            NOTES: response.data.VERIFICATION_DENIAL_NOTES
                        };
                    }
                    $scope.LoadingDenialInfo = false;
                }, function errorCallback(response) {
                    console.error(response.data.Message);
                    console.error(response);
                    if ($scope.ExceptionDialogControl != null) {
                        $scope.ExceptionDialogControl.showDialog("Error in retrieving verification denial information.");
                    }
                    else {
                        bootbox.alert(response.data.Message);
                    }
                    $scope.LoadingDenialInfo = false;
                });

                $('#DenialNotes' + $scope.name + 'Dialog').modal({
                    backdrop: 'static'
                });
                $('#DenialNotes' + $scope.name + 'Dialog').modal('show');
            }

            $scope.closeDenialNotesDialog = function () {
                $('#DenialNotes' + $scope.name + 'Dialog').modal('hide');
            }
        }]
    };
}]);

app.directive('wbxVerificationButton', [function () {
    return {
        restrict: 'E',
        templateUrl: '/Templates/VerificationButton',
        scope: {
            data: '=',
            submitFunction: '&'
        },
        controller: ['$scope', function ($scope) {
            $scope.submit = function (entity, isVerify) {
                $scope.submitFunction({ entity: entity, isVerify: isVerify});
            }
        }]
    };
}]);

app.directive('wbxMemberInfoFields', ['$http', '$q', '$timeout', function ($http, $q, $timeout) {
    return {
        restrict: 'E',
        templateUrl: '/Templates/MemberInfoFields',
        require: '^form',
        scope: {
            memberData: '=',
            fieldsReady: '=',
            enrolleeId: '=?',
            isDependent: '=?',
            isEdit: '=?',
            fullGender: '=?' /*Pass in the original data object with gender as 1 char to return the full gender string*/
        },
        controller: ['$scope', function ($scope) {
            
            $scope.init = function () {
                $scope.getStateList();
                if (!$scope.isEdit) {
                    $scope.getMaritalStatuses();
                }

            }
            $scope.fieldsReady = !( $scope.loadingMaritalStatusesList || $scope.loadingStateList);
           
            $scope.getStateList = function () {
                //if (scope.stateList == null) {
                $scope.LoadingStateList = true;
                $http({
                    method: 'GET',
                    url: '/PortalDropList/GetStates'
                }).then(function successCallback(response) {
                    $scope.stateList = response.data;

                    $scope.LoadingStateList = false;
                    //if ($scope.isEntityPanelLoaded())
                    //    $scope.showPanelBody('EntityPanelBody');

                }, function errorCallback(response) {
                    console.error(response.data.Message);
                    console.error(response);
                    if ($scope.ExceptionDialogControl != null) {
                        $scope.ExceptionDialogControl.showDialog("Error with populating state dropdown.");
                    }
                    else {
                        bootbox.alert(response.data.Message);
                    }
                    $scope.LoadingStateList = false;
                });
                //}
            }
           
            $scope.getMaritalStatuses = function () {
                $scope.maritalStatusesList = null;
                $scope.loadingMaritalStatusesList = true;
                $http({
                    method: 'GET',
                    url: '/Enrollee/GetMaritalStatuses'
                }).then(function successCallback(response) {
                    $scope.maritalStatusesList = response.data;

                    $scope.loadingMaritalStatusesList = false;
                    //if ($scope.isEntityPanelLoaded())
                    //    $scope.showPanelBody('EntityPanelBody');

                }, function errorCallback(response) {
                    $scope.loadingMaritalStatusesList = false;
                    console.error(response.data.Message);
                    console.error(response);
                    if ($scope.ExceptionDialogControl != null) {
                        $scope.ExceptionDialogControl.showDialog("Error with populating marital statuses.");
                    }
                    else {
                        bootbox.alert(response.data.Message);
                    }
                });
            }

            $scope.getSubscriberInfo = function () {
                $scope.loadingSubscriberInfo = true;
                $http({
                    method: 'GET',
                    url: '/MAP/AddMember/GetSubscriberInfo',
                    params: {
                        enrolleeId: $scope.enrolleeId
                    }
                }).then(function successCallback(response) {
                    $scope.subscriber = response.data;

                    //Populate memberData with Subscriber info
                    $scope.memberData.ADDRESS1 = $scope.subscriber.ADDRESS1;
                    $scope.memberData.ADDRESS2 = $scope.subscriber.ADDRESS2;
                    $scope.memberData.CITY = $scope.subscriber.CITY;
                    $scope.memberData.STATE = $scope.subscriber.STATE;
                    $scope.memberData.ZIP = $scope.subscriber.ZIP;
                    
                    $scope.loadingSubscriberInfo = false;
                }, function errorCallback(response) {
                    $scope.loadingSubscriberInfo = false;
                    console.error(response.data.Message);
                    console.error(response);
                    if ($scope.ExceptionDialogControl != null) {
                        $scope.ExceptionDialogControl.showDialog("Error populating subscriber information.");
                    }
                    else {
                        bootbox.alert(response.data.Message);
                    }
                });
            }

            $scope.GenderList = [
               {
                   VALUE: 'F',
                   DESCRIPTION: "Female"
               },
               {
                   VALUE: 'M',
                   DESCRIPTION: "Male"
               },
               {
                   VALUE: 'U',
                   DESCRIPTION: "Unknown"
               }
            ];

            $scope.$watch('isDependent', function (n, o) {
                if (n == true) {
                    $scope.getSubscriberInfo();
                }
            });
            $scope.$watch('fullGender.GENDER', function (n, o) {
                if (n != null) {
                    $scope.fullGender.GENDER_FULL = (_.findWhere($scope.GenderList, { VALUE: $scope.fullGender.GENDER })).DESCRIPTION;
                }
            });

            $scope.useSubscriberInfo_onclick = function() {
                if ($scope.memberData.UseSubscriberAddress) {
                    $scope.memberData.ADDRESS1 = $scope.subscriber.ADDRESS1;
                    $scope.memberData.ADDRESS2 = $scope.subscriber.ADDRESS2;
                    $scope.memberData.CITY = $scope.subscriber.CITY;
                    $scope.memberData.STATE = $scope.subscriber.STATE;
                    $scope.memberData.ZIP = $scope.subscriber.ZIP;
                } else {
                    $scope.memberData.ADDRESS1 = null;
                    $scope.memberData.ADDRESS2 = null;
                    $scope.memberData.CITY = null;
                    $scope.memberData.STATE = null;
                    $scope.memberData.ZIP = null;
                    $scope.memberData.ZIP_4 = null;
                }
            }
        }],
      
        link: function (scope, element, attr, formController) {
            scope.member_form = formController;
        }
    };
}]);

app.directive('wbxAdditionalInsuranceFields', ['$http', '$q', '$timeout','$window', function ($http, $q, $timeout, $window) {
    return {
        restrict: 'E',
        templateUrl: '/Templates/AdditionalInsuranceFields',
        require: '^form',
        scope: {
            policyData: '=',
            fieldsReady: '='
        },
    
        controller: ['$scope', function ($scope) {
            $scope.init = function () {
                $scope.getRelationshipCodes();
                }
            $scope.fieldsReady = !$scope.loadingRelationshipCodesList;
            $scope.getRelationshipCodes = function () {
                $scope.relationshipCodesList = null;
                $scope.loadingRelationshipCodesList = true;
                $http({
                    method: 'GET',
                    url: '/Enrollee/GetRelationshipCodes'
                }).then(function successCallback(response) {
                    $scope.relationshipCodesList = response.data;
                    var path = $window.location.pathname;
                    if (path == "/MAP/EnrollmentSummary") {
                        $scope.colName = 4;
                        $scope.colInput = 8;
                        $scope.OtherInsuranceModal = true;
                        return ($scope.OtherInsuranceModal);
                    }
                    else {
                        $scope.colName = 3;
                        $scope.colInput = 8;
                    }
                    
                    $scope.loadingRelationshipCodesList = false;
                }, function errorCallback(response) {
                    $scope.loadingRelationshipCodesList = false;
                    console.error(response.data.Message);
                    console.error(response);
                    if ($scope.ExceptionDialogControl != null) {
                        $scope.ExceptionDialogControl.showDialog("Error with populating relationship codes.");
                    }
                    else {
                        bootbox.alert(response.data.Message);
                    }
                });
            }
           
     $scope.GenderList = [
       {
           VALUE: 'F',
           DESCRIPTION: "Female"
       },
       {
           VALUE: 'M',
           DESCRIPTION: "Male"
       },
       {
           VALUE: 'U',
           DESCRIPTION: "Unknown"
       }
     ];

    $scope.PolicyTypeList = [
        {
            VALUE: 7,
            DESCRIPTION: "Unknown"
        },
        {
            VALUE: 6,
            DESCRIPTION: "Group Dental"
        },
        {
            VALUE: 5,
            DESCRIPTION: "Group Medical"
        },
        {
            VALUE: 1,
            DESCRIPTION: "Medicare Part A"
        },
        {
            VALUE: 2,
            DESCRIPTION: "Medicare Part B"
        },
        {
            VALUE: 3,
            DESCRIPTION: "Medicare Part C"
        },
        {
            VALUE: 4,
            DESCRIPTION: "Medicare Part D"
        }
    ];

        }],

        link: function (scope, element, attr, formController) {
            scope.add_member_form = formController;
        }
    };
}]);

app.directive('wbxMemberGridButtons', [function () {
    return {
        restrict: 'E',
        templateUrl: '/Templates/MemberGridButtons',
        scope: {
            control: '=',
            permissions: '=',
            data: '=',
            dialogData: '=',
            isGrid: '=',
            isAddDependent: '=?',
            isEnrollmentSummary: '=?',
            isEnrollmentSummaryInfo: '=?'
        },
        controller: ['$scope', '$window', 'ImpersonateService', function ($scope, $window, impersonateService) {
            $scope.filter = {
                benefitLvl: 1,
                locationId: -1,
                providerId: -1
            };

            $scope.gotoEnrollmentSummaryPage = function (insuredEnrolleeId, enrolleeId, planId, groupId, subscriberId) {
                window.location.href = "/MAP/EnrollmentSummary/SelectEnrollee?" + "InsuredEnrolleeId=" + insuredEnrolleeId + "&EnrolleeId=" + enrolleeId + "&GroupId=" + groupId + "&PlanId=" + planId + "&SubscriberId=" + subscriberId;
            };

            $scope.gotoAddDependent = function (enrolleeId, planId, groupId) {
                $window.location.href = "/MAP/AddMember/Index?EnrolleeId=" + enrolleeId + "&GroupId=" + groupId + "&PlanId=" + planId;
            }

            $scope.showBenefitSummaryReport = function (enrolleeId, productId, groupId) {
                var URL = '/Areas/MAP/Reports/BenefitSummary.aspx';
                var param = {
                    enrolleeId: enrolleeId,
                    productId: productId,
                    premiumGroupId: groupId,
                    benefitLvl: $scope.filter.benefitLvl,
                    locationId: $scope.filter.locationId,
                    providerId: $scope.filter.providerId

                };
                var result = URL + "?" + jQuery.param(param);
                window.open(result, "BenefitSummary", "resizable,scrollbars,width=1000,height=900", true);
            }

            $scope.showRequestIdCardDialog = function (enrolleeId, productId, firstName, lastName, address1, city, state, zip, groupIndex, planIndex) {
                $scope.dialogData.RequestIdInfo = {
                    ENROLLEE_ID: enrolleeId,
                    PRODUCT_ID: productId,
                    FIRST_NAME: firstName,
                    LAST_NAME: lastName,
                    ADDRESS: address1,
                    CITY: city,
                    STATE: state,
                    ZIP: zip,
                    GROUP_INDEX: groupIndex,
                    PLAN_INDEX: planIndex
                }
                $scope.determineWhereToShowAlert();
                impersonateService.getImpersonateSessionInfo()
                    .then(function (response) {
                  
                   $scope.control.isImpersonation = response.IsImpersonation;
                    $scope.control.impersonatedName = response.ImpersonatedName;
                    $scope.control.showRequestIdDialog();
                });
                
            }

            $scope.showIdCardReport = function (enrolleeId, productId, groupId) {
                var URL = '/Areas/MAP/Reports/MemberIDCard.aspx';
                var param = {
                    enrolleeId: enrolleeId,
                    productId: productId,
                    premiumGroupId: groupId,
                    benefitLvl: $scope.filter.benefitLvl,
                    locationId: $scope.filter.locationId,
                    providerId: $scope.filter.providerId

                };
                var result = URL + "?" + jQuery.param(param);
                window.open(result, "GetIDCard", "resizable,scrollbars,width=1000,height=900", true);
            }

            $scope.showEligibilityHistoryReport = function (enrolleeId) {
                var URL = '/Areas/MAP/Reports/EligibilityHistory.aspx';
                var param = {
                    enrolleeId: enrolleeId
                };

                var result = URL + "?" + jQuery.param(param);
                window.open(result, "ViewEligbility", "resizable,scrollbars,width=1000,height=900", true);
            };

            $scope.gotoOtherInsurance = function (insuredEnrolleeId, enrolleeId, planId, groupId, subscriberId) {
                window.location.href = "/MAP/EnrollmentSummary/SelectEnrollee?" + "InsuredEnrolleeId=" + insuredEnrolleeId + "&EnrolleeId=" + enrolleeId + "&GroupId=" + groupId + "&PlanId=" + planId + "&SubscriberId=" + subscriberId + '#bottom';
            };
            
            $scope.showTerminatePolicyDialog = function (enrolleeId, productId, premiumGroupId, firstName, lastName, benefitPlan, groupIndex, planIndex, dependentIndex) {
                $scope.dialogData.TerminateMemberInfo = {
                    ENROLLEE_ID: enrolleeId,
                    PRODUCT_ID: productId,
                    PREMIUM_GROUP_ID: premiumGroupId,
                    FIRST_NAME: firstName,
                    LAST_NAME: lastName,
                    BENEFIT_PLAN: benefitPlan,
                    GROUP_INDEX: groupIndex,
                    PLAN_INDEX: planIndex,
                    DEPENDENT_INDEX: dependentIndex,
                    TYPE: 1
                };
                $scope.determineWhereToShowAlert();

                impersonateService.getImpersonateSessionInfo()
                    .then(function (response) {                   
                   $scope.control.isImpersonation = response.IsImpersonation;
                    $scope.control.impersonatedName = response.ImpersonatedName; 
                    $scope.control.showTerminateMemberDialog();
                });
            }

            $scope.showDropDependentDialog = function (enrolleeId, productId, premiumGroupId, firstName, lastName, benefitPlan, groupIndex, planIndex, dependentIndex) {
                $scope.dialogData.TerminateMemberInfo = {
                    ENROLLEE_ID: enrolleeId,
                    PRODUCT_ID: productId,
                    PREMIUM_GROUP_ID: premiumGroupId,
                    FIRST_NAME: firstName,
                    LAST_NAME: lastName,
                    BENEFIT_PLAN: benefitPlan,
                    GROUP_INDEX: groupIndex,
                    PLAN_INDEX: planIndex,
                    DEPENDENT_INDEX: dependentIndex,
                    TYPE: 2
                };
                $scope.determineWhereToShowAlert();
                $scope.control.showTerminateMemberDialog();
            }

            $scope.determineWhereToShowAlert = function () {
                if ($scope.isEnrollmentSummary) {
                    //Only on enrollment summary page we need to determine where to show the alert
                    $scope.dialogData.IsAlertShownOnDependentLevel = $scope.isGrid;
                }
            }
        }]
    };
}]);

app.directive('wbxMemberGridModalDialogs', [function () {
    return {
        restrict: 'E',
        templateUrl: '/Templates/MemberGridModalDialogs',
        scope: {
            control: '=',
            data: '=',
            isSuccess: '=',
            message: '=',
            submit: '&'
        },
        controller: ['$scope', '$http', '$window', '$timeout', 'ImpersonateService', function ($scope, $http, $window, $timeout, impersonateService) {
            //Region Terminate policy and drop dependent
            $scope.$watch('data.TerminateMemberInfo.TYPE', function (n, o) {
                if (n != null && n != o) {
                    $scope.getTermReasonCodes($scope.data.TerminateMemberInfo.TYPE);
                }
            });

            $scope.initTerminateMember = function() {
                $timeout(function () {
                    $scope.ShowErrorBanner = false;
                    $scope.data.TerminateMemberInfo.TERM_REASON_CODE = null;
                    $scope.data.TerminateMemberInfo.TERM_REASON_EVENT_DATE = moment().startOf('day').format("MM/DD/YYYY");
                    impersonateService.getImpersonateSessionInfo()
                    .then(function (response) {                  
                        $scope.control.isImpersonation = response.IsImpersonation;
                        $scope.control.impersonatedName = response.ImpersonatedName;
                   
                    });
                });
            }

            $scope.getTermReasonCodes = function (type) {
                $scope.LoadingTermCodesList = true;
                $http({
                    method: 'GET',
                    url: '/Enrollee/getTermReasonCodes',
                    params: {
                        type: type
                    }
                }).then(function successCallback(response) {
                    $scope.TermCodesList = response.data;
                    $scope.LoadingTermCodesList = false;
                }), function errorCallback(response) {
                    console.error(response.data.Message);
                    console.error(response);
                    $scope.ExceptionDialogControl.showDialog("Error with populating Termination Reason codes.");
                    $scope.LoadingTermCodesList = false;
                }
            };

            $scope.submitTermination = function () {
                if(!$scope.control.isImpersonation)
                {
                if ($scope.terminate_member_form.$invalid) {
                    return false;
                }
                $scope.ShowTerminationProcessingBanner = true;
                if ($scope.data.TerminateMemberInfo.TYPE == 1) {
                    $scope.submitTerminatePolicy();
                }
                else if ($scope.data.TerminateMemberInfo.TYPE == 2) {
                    $scope.submitDropDependent();
                }
                }
                else {
                    return false;
                }
            }

            $scope.submitTerminatePolicy = function () {
                $http({
                    method: 'POST',
                    url: '/Enrollee/TerminatePolicy',
                    data: {
                        enrolleeId: $scope.data.TerminateMemberInfo.ENROLLEE_ID,
                        groupId: $scope.data.TerminateMemberInfo.PREMIUM_GROUP_ID,
                        productId: $scope.data.TerminateMemberInfo.PRODUCT_ID,
                        termReasonCode: $scope.data.TerminateMemberInfo.TERM_REASON_CODE,
                        termReasonEventDate: $scope.data.TerminateMemberInfo.TERM_REASON_EVENT_DATE
                    }
                }).then(function successCallback(response) {
                    $scope.ShowTerminationProcessingBanner = false;
                    if (response.data.Status == false) {
                        $scope.ErrorBannerMessage = response.data.Message;
                        $scope.ShowErrorBanner = true;
                    }
                    else {
                        $scope.isSuccess = response.data.Status;
                        if (response.data.Message != null)
                            $scope.message = "The policy has been terminated successfully with a termination date of " + response.data.Message + ".";
                        else
                            $scope.message = "The policy has been terminated successfully.";
                        $scope.control.hideTerminateMemberDialog();
                        $scope.submit();
                    }

                }, function errorCallback(response) {
                    console.error(response.data.Message);
                    console.error(response);
                    $scope.ExceptionDialogControl.showDialog("Error in terminating policy.");
                    $scope.ShowTerminationProcessingBanner = false;
                    $scope.control.hideTerminateMemberDialog();
                });
            };

            $scope.submitDropDependent = function () {
                $http({
                    method: 'POST',
                    url: '/Enrollee/DropDependent',
                    data: {
                        enrolleeId: $scope.data.TerminateMemberInfo.ENROLLEE_ID,
                        groupId: $scope.data.TerminateMemberInfo.PREMIUM_GROUP_ID,
                        productId: $scope.data.TerminateMemberInfo.PRODUCT_ID,
                        termReasonCode: $scope.data.TerminateMemberInfo.TERM_REASON_CODE,
                        termReasonEventDate: $scope.data.TerminateMemberInfo.TERM_REASON_EVENT_DATE
                    }
                }).then(function successCallback(response) {
                    $scope.ShowTerminationProcessingBanner = false;
                    if (response.data.Status == false) {
                        $scope.ErrorBannerMessage = response.data.Message;
                        $scope.ShowErrorBanner = true;
                    }
                    else {
                        $scope.isSuccess = response.data.Status;
                        $scope.message = "The dependent has been terminated successfully with a termination date of " + response.data.Message + ".";
                        $scope.control.hideTerminateMemberDialog();
                        $scope.submit();
                    }

                }, function errorCallback(response) {
                    console.error(response.data.Message);
                    console.error(response);
                    $scope.ExceptionDialogControl.showDialog("Error in Dropping Dependent.");
                    $scope.ShowTerminationProcessingBanner = false;
                    $scope.control.hideTerminateMemberDialog();
                });
            };

            //End Region Terminate policy and drop dependent

            //Region Request Id Card
            $scope.submitRequestIdCard = function () {
                if(!$scope.control.isImpersonation)
                {
                $scope.ShowRequestIdProcessing = true;
                $http({
                        method: 'PUT',
                        url: '/Enrollee/RequestIDCard',
                        params: {
                            enrolleeId: $scope.data.RequestIdInfo.ENROLLEE_ID,
                            productId: $scope.data.RequestIdInfo.PRODUCT_ID
                        }
                }).then(function successCallback(response) {
                    $scope.ShowRequestIdProcessing = false;
                    $scope.isSuccess = response.data.Status;
                    $scope.message = response.data.Message;
                    $scope.control.hideRequestIdDialog();
                    $scope.submit();
                    
                },function errorCallback(response) {
                    console.error(response.data.Message);
                    console.error(response);
                    $scope.ExceptionDialogControl.showDialog("Error with requesting id card.");
                    $scope.control.hideRequestIdDialog();
                    $scope.submit();
                    $scope.ShowRequestIdProcessing = false;
                });
                }
            }
            //End Region Request Id Card
        }],
        link: function (scope, element, attr) {
            scope.control = scope.control || {};
            scope.control.showRequestIdDialog = function () {
                $('#RequestIDCard').modal({
                    backdrop: 'static',
                    keyboard: false
                });

                $('#RequestIDCard').modal('show');
            };

            scope.control.hideRequestIdDialog = function () {
                $('#RequestIDCard').modal('hide');
            };

            scope.control.showTerminateMemberDialog = function () {
                scope.initTerminateMember();
                $('#TerminateMember').modal({
                    backdrop: 'static',
                    keyboard: false
                });

                $('#TerminateMember').modal('show');
            };

            scope.control.hideTerminateMemberDialog = function () {
                scope.terminate_member_form.$setPristine();
                $('#TerminateMember').modal('hide');
            };
        }
    };
}]);;
app.controller('ProviderSearchCtrl', ProviderSearchCtrl);
ProviderSearchCtrl.$inject = ['$scope', '$http', 'wbxProviderSearch', '$log', 'DataService', '$rootScope'];

function ProviderSearchCtrl($scope, $http, wbxProviderSearch, $log, DataService, $rootScope) {

    $scope.results = null;
    $scope.providerDetails = null;
    $scope.accessDetails = null;
    $scope.total = 0;
    $scope.publicSearch = false;
    $scope.customSearch = false;

    var lastName = "";
    var location = "";
    var locCity = "";
    var searchNear = "";
    var ProductId = null;
    var SpecialtyId = "-1";
    var LocationLanguage = null;
    var HandicapFlag = null;
    var SpecialNeedsFlag = null;
    var PcpEligible = null;
    var SortId = null;

    $scope.locationServices = false;
    $scope.loadingResults = false;
    $scope.natural = $rootScope.natural;
    var location = {};

    $scope.getLocation = function () {
        if (navigator.geolocation) {
            navigator.geolocation.getCurrentPosition(generatePosition, locationError);
            $scope.locationServices = true;
        } else {
            $scope.locationServices = false;
            $log.debug("Geolocation is not supported by this browser.");
        }
    }
    function generatePosition(position) {
        var result = {
            latitude: position.coords.latitude,
            longitude: position.coords.longitude,
            accuracy: position.coords.accuracy,
            position: position.coords
        };
        location = result;

    }

    function locationError(error) {
        $scope.locationServices = false;

        switch (error.code) {
            case error.PERMISSION_DENIED:

                break;
            case error.POSITION_UNAVAILABLE:

                break;
            case error.TIMEOUT:

                break;
            case error.UNKNOWN_ERROR:

                break;
        }
    }



    // Search options for the SP
    $scope.filter = {
        nearAddress: "",
        nearCity: "",
        nearState: "",
        nearZip: "",
        productId: null,
        providerLastName: "",
        locationName: "",
        city: "",
        specialtyId: -1,
        locationLanguage: null,
        OnlineProviders: "",
        handicapFlag: false,
        specialNeedsFlag: false,
        pcpEligible: false,
        sortId: 1
    };

    $scope.init = function () {

        if (DataService.OnlineProviders != null) {
            $scope.filter.includeOnlineProvidersFlag = DataService.OnlineProviders;
        }
        else {
            $scope.filter.includeOnlineProvidersFlag = true;
        }
    }
         $scope.setPageTitle = function(title) {
            document.title = title;
        }

    $scope.sortColumn = function (keyname) {
            $scope.fieldSort = keyname;
            $scope.reverse = !$scope.reverse;
        }

    $scope.GetEnrolleeDetails = function () {
        $scope.publicSearch = false;
        // Make the search call
        $http({
            url: '/ProviderSearch/GetEnrolleeDetails',
            method: 'GET',
            params: {
            }
        }).then(function (data) {
            data = data.data;

            if (data.length == 0) {
                $scope.providerDetails = null;
                bootbox.alert("Could not retrieve enrollee details.");
            }
            else {
                $scope.filter.nearAddress = data[0].ADDRESS1;
                $scope.filter.nearCity = data[0].CITY;
                $scope.filter.nearState = data[0].STATE;
                $scope.filter.nearZip = data[0].ZIP;
            }

        });


    };

    $scope.Search = function () {
        if (DataService.DirectSearch != null) {
            $scope.publicSearch = DataService.DirectSearch;
        }
        
        if (DataService.CustomSearch != null)
        {
            $scope.customSearch = DataService.CustomSearch;
            if($scope.customSearch == true)
            {
                $scope.publicSearch = true;
            }
        }       
        
        
        if($scope.filter.includeOnlineProvidersFlag === undefined)
        {
            if (DataService.OnlineProviders != null) {
                $scope.filter.includeOnlineProvidersFlag = DataService.OnlineProviders;
            }
            else 
            {
                $scope.filter.includeOnlineProvidersFlag = true;
            }
        }
        else
        { 
        $scope.filter.includeOnlineProvidersFlag = $scope.filter.includeOnlineProvidersFlag;
        }
        
        // check the params being sent to be in the correct format 
        searchNear = "";

        if ($scope.filter.nearAddress != undefined && $scope.filter.nearAddress.length != 0) {
            searchNear += $scope.filter.nearAddress;
            searchNear += "  ";
        }

        if ($scope.filter.nearCity != undefined && $scope.filter.nearCity.length != 0) {
            searchNear += "  ";
            searchNear += $scope.filter.nearCity;
        }

        if ($scope.filter.nearState != undefined && $scope.filter.nearState.length != 0) {
            searchNear += "  ";
            searchNear += $scope.filter.nearState;
        }

        if ($scope.filter.nearZip != undefined && $scope.filter.nearZip.length != 0) {
            searchNear += " , ";
            searchNear += $scope.filter.nearZip;
        }

        if (searchNear.length == 0)
            searchNear = null;


        if ($scope.filter.providerLastName == undefined && $scope.filter.providerLastName.length == 0) {
            lastName = null;
        }
        else
            lastName = $scope.filter.providerLastName;

        if ($scope.filter.locationName == undefined && $scope.filter.locationName.length == 0) {
            location = null;
        }
        else
            location = $scope.filter.locationName;

        if ($scope.filter.city == undefined && $scope.filter.city.length == 0) {
            locCity = null;
        }
        else
            locCity = $scope.filter.city;

        if ($scope.filter.nearZip != undefined && $scope.filter.nearZip.length < 5) {
            bootbox.alert("Invalid zip. Zip must be minimum 5 characters");
            return;
        }

        if ($scope.filter.nearZip == undefined && $scope.filter.nearZip.length == 0) {
            if ($scope.filter.nearCity.length == 0 && $scope.filter.nearState.length == 0) {
                bootbox.alert("You must specify a city and a state.");
                return;
            }
        }

        if ($scope.filter.nearCity == undefined || $scope.filter.nearCity.length == 0 || $scope.filter.nearState == undefined || $scope.filter.nearState.length == 0) {
            if ($scope.filter.nearZip.length == 0) {
                bootbox.alert("You must specify a city and state or a zip.");
                return;
            }
        }


        //if (($scope.filter.nearCity.length  + $scope.filter.nearState.length + $scope.filter.nearZip.length) == 0) {
        //    bootbox.alert("You must specify a city, state, or zip.");
        //    return;
        //}

        SpecialtyId = $scope.filter.specialtyId;
        LocationLanguage = $scope.filter.locationLanguage;
        HandicapFlag = $scope.filter.handicapFlag;
        SpecialNeedsFlag = $scope.filter.specialNeedsFlag;
        PcpEligible = $scope.filter.pcpEligible;
        SortId = $scope.filter.sortId;
        $scope.total = 0;

        if ($scope.$parent.selectPCPProductId != null)
            ProductId = $scope.$parent.selectPCPProductId;

        $scope.pagingOptions.pageSize = 8;
        $scope.pagingOptions.currentPage = 1;

        $scope.getPagedDataAsync($scope.pagingOptions.pageSize, $scope.pagingOptions.currentPage);
    };

    $scope.InitSearch = function (address, city, state, zip, PCP) {
        $scope.filter.nearAddress = address;
        $scope.filter.nearCity = city;
        $scope.filter.nearState = state;
        $scope.filter.nearZip = zip;
        $scope.filter.pcpEligible = PCP;
    }

    $scope.InitPCPSearch = function (address, city, state, zip, PCP, groupId, planId) {
        $scope.filter.nearAddress = address;
        $scope.filter.nearCity = city;
        $scope.filter.nearState = state;
        $scope.filter.nearZip = zip;
        $scope.filter.pcpEligible = PCP;
        ProductId = planId;
    }


    $scope.QuickSearch = function (address, city, state, zip, bPublicSearch, bCustomSearch) {
        if (DataService.OnlineProviders != null) {
            $scope.filter.includeOnlineProvidersFlag = DataService.OnlineProviders;
        }
        else {
            $scope.filter.includeOnlineProvidersFlag = true;
        }
        $scope.publicSearch = bPublicSearch;
        $scope.customSearch = parseBool(bCustomSearch);
        $scope.results = null;

        if (address.length != 0)
            $scope.filter.nearAddress = address;

        if (city.length != 0)
            $scope.filter.nearCity = city;

        if (state != -1)
            $scope.filter.nearState = state;

        if (zip.length != 0)
            $scope.filter.nearZip = zip;

        // check the params being sent to be in the correct format 
        searchNear = "";


        if ($scope.filter.nearAddress.length != 0) {
            searchNear += $scope.filter.nearAddress;
            searchNear += "  ";
        }

        if ($scope.filter.nearCity.length != 0) {
            searchNear += "  ";
            searchNear += $scope.filter.nearCity;
        }

        if ($scope.filter.nearState.length != 0) {
            searchNear += "  ";
            searchNear += $scope.filter.nearState;
        }

        if ($scope.filter.nearZip.length != 0) {
            searchNear += " , ";
            searchNear += $scope.filter.nearZip;
        }

        if (searchNear.length == 0)
            searchNear = null;


        if ($scope.filter.providerLastName.length == 0) {
            lastName = null;
        }
        else
            lastName = $scope.filter.providerLastName;

        if ($scope.filter.locationName.length == 0) {
            location = null;
        }
        else
            location = $scope.filter.locationName;

        if ($scope.filter.city.length == 0) {
            locCity = null;
        }
        else
            locCity = $scope.filter.city;

        /* special case, AddMember page using embedded doesn't need a quick search at startup */
        if ($scope.filter.nearZip == '0') {
            $scope.filter.nearZip = '';
            return;
        }

        if ($scope.filter.nearZip.length == 0) {
            if ($scope.filter.nearCity.length == 0 && $scope.filter.nearState.length == 0) {
                bootbox.alert("You must specify a city and a state.");
                return;
            }
        }

        if ($scope.filter.nearCity.length == 0 || $scope.filter.nearState.length == 0) {
            if ($scope.filter.nearZip.length == 0) {
                bootbox.alert("You must specify a city and state or a zip.");
                return;
            }
        }

        //if (($scope.filter.nearCity.length + $scope.filter.nearState.length + $scope.filter.nearZip.length) == 0) {
        //    bootbox.alert("You must specify a city, state, or zip.");
        //    return;
        //}

        SpecialtyId = $scope.filter.specialtyId;
        LocationLanguage = $scope.filter.locationLanguage;
        HandicapFlag = $scope.filter.handicapFlag;
        SpecialNeedsFlag = $scope.filter.specialNeedsFlag;
        PcpEligible = $scope.filter.pcpEligible;
        SortId = $scope.filter.sortId;
        $scope.total = 0;
        $scope.pagingOptions.pageSize = 10;
        $scope.pagingOptions.currentPage = 1;


        $scope.getPagedDataAsync($scope.pagingOptions.pageSize, $scope.pagingOptions.currentPage);
    };

    $scope.refineSearch = function () {
        $scope.results = null;
    }

    $scope.hasResults = function () {
        if ($scope.results === null || $scope.results === undefined) {
            return false;
        }
      return ($scope.results.length > 0);
    };

    $scope.hasAccessResults = function () {
        if ($scope.accessDetails == null) {
            return false;
        }
        return ($scope.accessDetails.length > 0);
    };

    $scope.showProviderInfo = function (excludeProviders, Providers) {

        if (excludeProviders == true) {
            return false;
        }

        if ((excludeProviders == false) && (Providers == true))
            return true;
        else
            return false;
    };

    $scope.Reset = function () {
        $scope.results = null;

        $scope.filter.nearAddress = "";
        $scope.filter.nearCity = "";
        $scope.filter.nearState = "";
        $scope.filter.nearZip = "";
        $scope.filter.productId = null;
        $scope.filter.providerLastName = "";
        $scope.filter.locationName = "";
        $scope.filter.city = "";
        $scope.filter.specialtyId = "-1";
        $scope.filter.locationLanguage = null;
        $scope.filter.handicapFlag = false;
        $scope.filter.specialNeedsFlag = false;
        //$scope.filter.pcpEligible = false;        // this shouldn't be changed on reset
        $scope.filter.sortId = 1;


        var lastName = "";
        var location = "";
        var locCity = "";
        var searchNear = "";
        var ProductId = null;
        var SpecialtyId = "-1";
        var LocationLanguage = null;
        var HandicapFlag = null;
        var SpecialNeedsFlag = null;
        var PcpEligible = null;
        var SortId = null;


    };

    $scope.GetDetails = function (providerID, locationID) {

        $http({
            url: '/Public/Details',
            method: 'GET',
            params: {
                ProviderID: providerID,
                LocationID: locationID
            }
        }).then(function (data) {
            data = data.data;

            if (data.length == 0) {
                $scope.providerDetails = null;
                bootbox.alert("Could not retrieve provider details.");
            }
            else {
                $scope.providerDetails = data[0];
                $scope.setPageTitle('Provider Search Details');
                $http({
                    url: '/Public/GetAccessRestrictions',
                    method: 'GET',
                    params: {
                        LocationID: locationID
                    }
                }).then(function (data) {
                    data = data.data;

                    if (data.length == 0) {
                        $scope.accessDetails = null;
                    }
                    else {
                        $scope.accessDetails = data;
                    }
                    $('#details-modal').modal('show');

                }, function (data) {
                    $.unblockUI();
                    bootbox.alert(data);
                });



                $('#details-modal').modal('show');
            }

        }, function (data) {
            $.unblockUI();
            bootbox.alert(data);
        });

    };

$scope.openDirectionsWindow = function ()
{
    var address1 = $scope.providerDetails.ADDRESS1 != null ? $scope.providerDetails.ADDRESS1 + " " : "";
    var address2 = $scope.providerDetails.ADDRESS2 !=null ? $scope.providerDetails.ADDRESS2 + " " : "";
    var city =  $scope.providerDetails.CITY !=null ? $scope.providerDetails.CITY + " " : "";
    var state = $scope.providerDetails.STATE != null ? $scope.providerDetails.STATE + " " : "";
    var zip = $scope.providerDetails.ZIP !=null ? $scope.providerDetails.ZIP: "";
    var address = address1+address2+city+state+zip;
    window.open('https://www.google.com/maps/dir/?api=1&destination=' + address, '_blank');
}

    /* PCP selection was made, broadcast the change, AddMember's ng model needs the selection */
    $scope.SetPCP = function (providerID, locationID, lastname, firstname) {

        var msg = {
            Message: "PCP Selected by User",
            MessageType: "PCPSelection",
            ProviderID: providerID,
            LocationID: locationID,
            LastName: lastname,
            FirstName: firstname
        }

        wbxProviderSearch.prepForBroadcast(msg);

    };




    /* paging */

    $scope.orderBy = function (col) {
        $scope.pagingOptions.orderBy = col;
        $scope.getPagedDataAsync($scope.pagingOptions.pageSize, $scope.pagingOptions.currentPage);

    };

    $scope.pagingOptions = {
        pageSizes: [10, 50, 100],
        pageSize: 10,
        totalServerItems: 0,
        currentPage: 1,
        orderBy: null
    };

    $scope.totalPages = function () {
return Math.ceil($scope.total / $scope.pagingOptions.pageSize);
    }


    $scope.getPagedDataAsync = function (pageSize, page) {
        $scope.loadingResults = true;
        if ($scope.publicSearch === true) {
            setTimeout(function () {
                var data;

                $http({
                    url: '/Public/PreloginSearch',
                    method: 'GET',
                    params: {
                        address: searchNear,
                        productId: ProductId,
                        providerLastName: lastName,
                        locationName: location,
                        city: locCity,
                        specialtyId: SpecialtyId,
                        locationLanguage: LocationLanguage,
                        handicapFlag: HandicapFlag,
                        specialNeedsFlag: SpecialNeedsFlag,
                        pcpEligible: PcpEligible,
                        sortId: SortId,
                        customSearch: $scope.customSearch,
                        page: $scope.pagingOptions.currentPage,
                        pageSize: $scope.pagingOptions.pageSize,
                        total: $scope.total,
                        onlineOnlyProviders : $scope.filter.includeOnlineProvidersFlag 
                    }
                }).then(function (response) {
                    if (response.data != null && response.data.error !== true) {  
                            if (response.data.onlineProvidersData !== null || response.data.regularProvidersData !== null)
                                {
                                    $scope.loadingResults = false;
                                    $scope.errorMessage = false;
                                    $scope.total = response.data.total;
                                    $scope.results = response.data.regularProvidersData;
                                    if ($scope.filter.includeOnlineProvidersFlag) 
                                    {
                                        $scope.providerResults = response.data.onlineProvidersData;
                                    }
                                    else {
                                        $scope.providerResults = null;
                                    }
                                }
                                
                                if (!$scope.$$phase)
                                    $scope.$apply();   
                    }
                    else {
                        $scope.loadingResults = false;
                        $scope.results = null;
                        $scope.providerResults = null;
                        $scope.errorMessage = response.data.message
                    }
                }, function (data) {
                    $scope.loadingResults = false;
                    $.unblockUI();
                });

            }, 100);


        }
        else {

            if ($scope.$parent.PCPRequired && $scope.$parent.data.BenefitPlanId != null)
                ProductId = $scope.$parent.data.BenefitPlanId;
            if(!!DataService.productId)
                ProductId = DataService.productId
            setTimeout(function () {
                var data;

                $http({
                    url: '/ProviderSearch/Search',
                    method: 'GET',
                    params: {
                        address: searchNear,
                        productId: ProductId,
                        providerLastName: lastName,
                        locationName: location,
                        city: locCity,
                        specialtyId: SpecialtyId,
                        locationLanguage: LocationLanguage,
                        handicapFlag: HandicapFlag,
                        specialNeedsFlag: SpecialNeedsFlag,
                        pcpEligible: PcpEligible,
                        sortId: SortId,
                        customSearch: $scope.customSearch,
                        page: $scope.pagingOptions.currentPage,
                        pageSize: $scope.pagingOptions.pageSize,
                        total: $scope.total
                    }
                }).then(function (response) {
                    largeLoad = response.data;
                    if (largeLoad.total == 0) {
                        $scope.loadingResults = false;
                        bootbox.alert("No providers found based on the criteria selected.");
                    }
                    else {

                        if (largeLoad.error) {
                            $scope.loadingResults = false;
                            bootbox.alert(largeLoad.message);
                        }
                        else {
                            $scope.loadingResults = false;
                            $scope.total = largeLoad.total;
                            $scope.results = largeLoad.data;

                            if (!$scope.$$phase)
                                $scope.$apply();
                        }

                    }
                }, function (data) {
                    $scope.loadingResults = false;
                    $.unblockUI();
                    bootbox.alert(data);
                });

            }, 100);
        }
    };

    $scope.first = function () {
       $scope.pagingOptions.currentPage = 1;
    }

    $scope.last = function () {
        $scope.pagingOptions.currentPage = $scope.totalPages();
    }

    $scope.next = function () {
        if ($scope.pagingOptions.currentPage < $scope.totalPages()) {
            $scope.pagingOptions.currentPage++;
        }
    }

    $scope.previous = function () {
        if ($scope.pagingOptions.currentPage > 1) {
            $scope.pagingOptions.currentPage--;
        }
    }


    $scope.$watch('pagingOptions', function (newVal, oldVal) {
        if (newVal !== oldVal && newVal.currentPage !== oldVal.currentPage) {
            $scope.getPagedDataAsync($scope.pagingOptions.pageSize, $scope.pagingOptions.currentPage);
        }
    }, true);



    /* end paging */
    $scope.splitCsv = function (str) {
        if (str == '' || str == null) {
            return '';
        }
        return str.split(',').join(', ');
    };
}


function parseBool(value) {
    return (typeof value === "undefined") ?
        false :
        // trim using jQuery.trim()'s source 
        value.replace(/^\s+|\s+$/g, "").toLowerCase() === "true";
};
(function () {
    'use strict';
    function trapFocus(element) {
        const focusableEls = element.querySelectorAll('a[href]:not([disabled]), button:not([disabled]), textarea:not([disabled]), input[type="text"]:not([disabled]), input[type="radio"]:not([disabled]), input[type="checkbox"]:not([disabled]), select:not([disabled])');
        const firstFocusableEl = focusableEls[0];
        const lastFocusableEl = focusableEls[focusableEls.length - 1];
        const KEYCODE_TAB = 9;

        element.addEventListener('keydown', function (e) {
            var isTabPressed = (e.key === 'Tab' || e.keyCode === KEYCODE_TAB);

            if (!isTabPressed) {
                return;
            }

            if (e.shiftKey) /* shift + tab */ {
                if (document.activeElement == firstFocusableEl) {
                    lastFocusableEl.focus();
                    e.preventDefault();
                }
            } else /* tab */ {
                if (document.activeElement == lastFocusableEl) {
                    firstFocusableEl.focus();
                    e.preventDefault();
                }
            }

        });
    }
    $(document).ready(function () {
        for (let index = 0; index < $(".modal").length; index++) {
            trapFocus($(".modal")[index])
        }
    })
})();;
(function () {
    'use strict';

    app.service('FeatureFlagService', FeatureFlagService);

    FeatureFlagService.$inject = ['API'];

    function FeatureFlagService(API) {
        var services = {
            getFeatureFlagsForPWPVisionMedicaid: getFeatureFlagsForPWPVisionMedicaid,
            getFeatureFlagsForPWPDentalBenefitSummaryReport: getFeatureFlagsForPWPDentalBenefitSummaryReport,
            getFeatureFlagForSurfly: getFeatureFlagForSurfly
        };
        return services;

        function getFeatureFlagsForPWPVisionMedicaid() {
            return API.get("/FeatureFlag/GetFeatureFlagsForPWPVisionMedicaid")
                .then(function (response) {
                    return response;
                });
        }

        function getFeatureFlagsForPWPDentalBenefitSummaryReport() {
            return API.get("/FeatureFlag/GetFeatureFlagsForPWPDentalBenefitSummaryReport")
                .then(function (response) {
                    return response;
                });
        }

        function getFeatureFlagForSurfly() {
            return API.get("/FeatureFlag/GetFeatureFlagForSurfly")
                .then(function (response) {
                    return response;
                });
        }
    };
})();;
(function () {
    'use strict';

    app.service('GoogleTagManagerService', GoogleTagManagerService);

    GoogleTagManagerService.$inject = ['API','$window','$location'];

    function GoogleTagManagerService(api,$window,$location) {
        let vm = this;
        
        var service = {
            setPageInfo: setPageInfo,
            setClickInfo: setClickInfo
        };

        return service;

        function getPageInfo() {
            return api.get("/GoogleTagManager/GetGoogleTagManagerPageInfo")
                .then(function (response) {
                    return response;
                });
        }

        function setPageInfo(pageName, additionalPageReferrerUrl) {
            getPageInfo()
                .then(response => {
                    const getPageInfo = {
                        'event': 'custom_pageview',
                        'env': ((!response.Environment) ? response.Environment : response.Environment.toLowerCase()),
                        'app_source': 'web',
                        'digital_asset': ((!response.PortalType) ? response.PortalType : response.PortalType.toLowerCase()),
                        'portal_sub_type': ((!response.PortalSubType) ? response.PortalSubType : response.PortalSubType.toLowerCase()),
                        'line_of_business': ((!response.LineOfBusiness) ? response.LineOfBusiness : response.LineOfBusiness.toLowerCase()),
                        'page_location': ((!$location.absUrl()) ? $location.absUrl() : $location.absUrl().toLowerCase()),
                        'page_title': ((!pageName) ? pageName : pageName.toLowerCase()),
                        'page_referrer': ((!additionalPageReferrerUrl) ? ((!response.PageReferrer) ? response.PageReferrer : response.PageReferrer.toLowerCase()) : ((!response.PageReferrer) ? response.PageReferrer : response.PageReferrer.toLowerCase()) + additionalPageReferrerUrl.toLowerCase()),
                        'entity_id': response.EntityId,
                        'entity_type': ((!response.EntityType) ? response.EntityType : response.EntityType.toLowerCase()),
                        'entity_name': ((!response.EntityName) ? response.EntityName : response.EntityName.toLowerCase()),
                        'entity_state': ((!response.EntityState) ? response.EntityState : response.EntityState.toLowerCase()),
                        'user_id': response.DomainSourceId,
                        'network_name': ((!response.NetworkNames) ? response.NetworkNames : response.NetworkNames.toLowerCase()),
                        'network_id': response.NetworkIds
                    };
                    $window.dataLayer = $window.dataLayer || [];
                    $window.dataLayer.push(getPageInfo);
                });
        }

        function setClickInfo(action, attribute1, attribute2, attribute3, attribute4, category, label) {
            const getClickInfo = {
                'event': 'custom_event',
                'action': ((!action) ? action : action.toLowerCase()),
                'attribute1': ((!attribute1) ? attribute1 : attribute1.toLowerCase()),
                'attribute2': ((!attribute2) ? attribute2 : attribute2.toLowerCase()),
                'attribute3': ((!attribute3) ? attribute3 : attribute3.toLowerCase()),
                'attribute4': ((!attribute4) ? attribute4 : ((angular.isString(attribute4)) ? attribute4.toLowerCase() : attribute4)),
                'category': ((!category) ? category : category.toLowerCase()),
                'label': ((!label) ? label : label.toLowerCase())
            };
            $window.dataLayer = $window.dataLayer || [];
            $window.dataLayer.push(getClickInfo);
        }
}})();;
(function () {
    'use strict';

    app.service('ImpersonateService', ImpersonateService);

    ImpersonateService.$inject = ['API'];

    function ImpersonateService(api) {
        var service = {
            getImpersonateSessionInfo: getImpersonateSessionInfo
        };

        return service;

        function getImpersonateSessionInfo() {
            return api.get("/Impersonate/GetImpersonateSessionInfo")
                .then(function (response) {
                    return response;
                });
        }
    }
})();;
(function () {
    "use strict";
    app.factory('PipeUtilityService', PipeUtilityService);

    PipeUtilityService.$inject = [];

    function PipeUtilityService() {
        var services = {
            ObjectToCamelCase: ObjectToCamelCase
        };
        return services;

        // TODO: replace .map and make IE safe
        function ObjectToCamelCase (object) {
            if (isObject(object)) {
                const newObject = {};

                Object.keys(object)
                    .forEach((key) => {
                        newObject[toCamel(key)] = ObjectToCamelCase(object[key]);
                    });

                return newObject;
            } else if (isArray(object)) {
                return object.map((item) => {
                    return ObjectToCamelCase(item);
                });
            }

            return object;
        };
        
        function toCamel(word) {
            
            if (word === word.toUpperCase()) {
                word = word.toLowerCase();
            }

            if (word.indexOf('_') === -1 && word.indexOf('-') === -1) {
                word = pascalCaseToUnderScore(word);
            }
            word = word.toLowerCase();
            return word.replace(/([-_][a-z])/ig, ($1) => {
                return $1.toUpperCase()
                    .replace('-', '')
                    .replace('_', '');
            });
        };

        function pascalCaseToUnderScore(word) {
            return word.replace(/(?:^|\.?)([A-Z])/g, function (x, y) { return "_" + y.toLowerCase() }).replace(/^_/, "");
        }

        function isObject (suspectedObject) {
            return suspectedObject === Object(suspectedObject) && !isArray(suspectedObject) && typeof suspectedObject !== 'function';
        };

        function isArray (suspectedArray) {
            return Array.isArray(suspectedArray);
        };

        /*
        for unit tests
        let test = {
                test_test1: "value",
                TEST_TEST2: "value",
                TestTest3: "value",
                'TEST-TEST4': "value",
                'test-test5': "value",
                'Test-Test6': "value",
                test_test7: {
                    test_test8: 'value',
                    test_test9: 'value',
                    test_Test10: {
                        test_test11: 'value',
                        test_test12: 'value'
                    }
                },
                TESTT: 'test',
                test_test13: ['value', 'value']
            };
        */
    }
})();;
(function () {
    'use strict';
    angular
        .module('MWPApp')
        .controller('LayoutCtrl', LayoutCtrl);

    LayoutCtrl.$inject = ['$translate', 'LayoutService', 'ViewVersionCheckService', '$timeout', 'ImpersonateService', 'BillingInformationService', '$q', 'FeatureFlagService'];
    function LayoutCtrl($translate, LayoutService, viewVersionCheckService, $timeout, impersonateService, billingInformationService, $q, featureFlagService) {
        var vm = this;
        vm.languages = ["en"];
        vm.selectedLanguageCode = "en";
        vm.showAlert = false;
        vm.isBillingInformationAvailable = false;
        vm.isHasLifeInsuranceProductsMethodExecuted = false;

        vm.init = function (languageCode, languages, isAuthenticated) {
            vm.languages = JSON.parse(languages);
            vm.selectLanguage(languageCode);

            featureFlagService.getFeatureFlagForSurfly()
                .then(function (response) {
                    vm.surflyScript(response.IsSurflyLiveChatEnabled)
                });

            if (isAuthenticated) {
                impersonateService.getImpersonateSessionInfo()
                    .then(function (response) {
                        vm.isImpersonation = response.IsImpersonation;
                        vm.impersonatedName = response.ImpersonatedName;
                    });

                featureFlagService.getFeatureFlagsForPWPDentalBenefitSummaryReport()
                    .then(function (response) {
                        vm.isPwpDentalBenefitSummaryReportEnabled = response.IsPwpDentalBenefitSummaryReportEnabled;
                        vm.showBenefitSummaryLink = response.ShowBenefitSummaryLink;
                    });

                $q.all([
                    LayoutService.isIndividualEnrollment(),
                    billingInformationService.isDependent(),
                    billingInformationService.hasIndividualPaymentMethods()
                ]).then(function (results) {
                    let isIndividualEnrollment = results[0];
                    let isDependent = results[1]?.data;
                    let hasIndividualPaymentMethods = results[2]?.data;

                    vm.isBillingInformationAvailable = !isDependent && (isIndividualEnrollment || hasIndividualPaymentMethods);
                });
            }
        }

        vm.surflyScript = function (isEnabled) {
            if (isEnabled) {
                var head = document.getElementsByTagName('head')[0];
                var script = document.createElement('script');
                script.text = `(function (s, u, r, f, l, y) {
                    s[f] = s[f] || { init: function () { s[f].q = arguments } };
                    l = u.createElement(r); y = u.getElementsByTagName(r)[0]; l.async = 1;
                    l.src = 'https://surfly.com/surfly.js'; y.parentNode.insertBefore(l, y);
                })
                    (window, document, 'script', 'Surfly');

                var settings = {
                    // Surfly session options can be set here, or at the Company/Plan levels.
                    widget_key: '778564f3af0449b5a8528223ecbbb348',
                    private_session: true, // to make sure only logged in agents can join the call
                    require_password: false,
                };

                Surfly.init(settings, function (initResult) {
                    if (initResult.success) {
                        // API calls can now be made!
                        if (!Surfly.isInsideSession) {
                            Surfly.button();
                        }
                    }
                    else {
                        console.log("Surfly was unable to initialize properly.")
                    }
                });`;
                head.appendChild(script);
            }
        }
        vm.initBanners = function () {
            //workaround: delay to let  NVDA detect the change. ID IE needs more time. Better solution,  avoid vm.showAlert (is used for the autodismiss feature) and use ng-bind or translate attribute instead {{expression}}
            const timeToDisplayBanner = window.document.documentMode == undefined ? 1000 : 2000;
            $timeout(function () { vm.showAlert = true }, timeToDisplayBanner)

        }

        vm.selectLanguage = function (languageCode) {
            if (languageCode === undefined || languageCode === "")
                languageCode = 'en';

            vm.selectedLanguageCode = languageCode;

            LayoutService.setLanguageCode(languageCode);

            $translate.use(languageCode);
            angular.element('#language-selection-changed').focus();
        };

        vm.removeFocusClassOnBlur = function (e) {
            var isNavDropdownOption = angular.element(e.relatedTarget).parents(':eq(3)').hasClass('nav');

            if (!isNavDropdownOption) {
                angular.element('.menu-option').removeClass('focus');
                angular.element('.dropdown-menu-option').removeClass('focus');
            }
        };

        vm.removeFocusClassOnTab = function (e) {
            var keycode = (e.keyCode ? e.keyCode : e.which);

            if (keycode === '9') {
                angular.element('.dropdown-menu-option').removeClass('focus');
                e.stopPropagation();
            }
        };

        vm.addFocusClassOnTab = function (e) {
            var keycode = (e.keyCode ? e.keyCode : e.which);

            if (keycode === '9') {
                angular.element(e.currentTarget).addClass('focus');
                e.stopPropagation();
            }
        };


        vm.hasLifeInsuranceProducts = function () {
            if (!vm.isHasLifeInsuranceProductsMethodExecuted) {
                vm.isHasLifeInsuranceProductsMethodExecuted = true;
                LayoutService.hasLifeInsuranceProducts()
                    .then(function (response) {
                        vm.hasLifeInsuranceProductsFlag = response;
                    });
            }
        };
    }
})();

;
(function () {
    'use strict';
    angular.module('MWPApp')
        .service("LayoutService", LayoutService);

    LayoutService.$inject = ['API', '$q'];

    function LayoutService(API, $q) {
        var vm = this;
        vm.baseUrl = '/MWP/Landing/'

        vm.setLanguageCode = function (languageCode) {           
            var deferred = $q.defer();
            API.post(vm.baseUrl + 'SetLanguageCode', { languageCode: languageCode }).then(
                function (ok) {
                    deferred.resolve(ok);
                },
                function (failed) {
                    deferred.reject(failed);
                });
            return deferred.promise;
        }

        vm.isIndividualEnrollment = function () {
            return API.get(vm.baseUrl + 'IsIndividualEnrollment')
                .then(function (response) {
                    return response.data;
                });
        }

        vm.hasLifeInsuranceProducts = function() {
            return API.get(vm.baseUrl + 'HasLifeInsuranceProducts')
                .then(function (response) {
                    return response.data;
                });
        }

        vm.showBeneficiaryDesignationBanner = function () {
            return API.get(vm.baseUrl + 'ShowBeneficiaryDesignationBanner')
                .then(function (response) {
                    return response.data;
                });
        }
    }
})();;
/*
 * Inline Form Validation Engine 2.6.2, jQuery plugin
 *
 * Copyright(c) 2010, Cedric Dugas
 * http://www.position-absolute.com
 *
 * 2.0 Rewrite by Olivier Refalo
 * http://www.crionics.com
 *
 * Form validation engine allowing custom regex rules to be added.
 * Licensed under the MIT License
 */
 (function($) {

	"use strict";

	var methods = {

		/**
		* Kind of the constructor, called before any action
		* @param {Map} user options
		*/
		init: function(options) {
			var form = this;
			if (!form.data('jqv') || form.data('jqv') == null ) {
				options = methods._saveOptions(form, options);
				// bind all formError elements to close on click
				$(document).on("click", ".formError", function() {
					$(this).fadeOut(150, function() {
						// remove prompt once invisible
						$(this).parent('.formErrorOuter').remove();
						$(this).remove();
					});
				});
			}
			return this;
		 },
		/**
		* Attachs jQuery.validationEngine to form.submit and field.blur events
		* Takes an optional params: a list of options
		* ie. jQuery("#formID1").validationEngine('attach', {promptPosition : "centerRight"});
		*/
		attach: function(userOptions) {

			var form = this;
			var options;

			if(userOptions)
				options = methods._saveOptions(form, userOptions);
			else
				options = form.data('jqv');

			options.validateAttribute = (form.find("[data-validation-engine*=validate]").length) ? "data-validation-engine" : "class";
			if (options.binded) {

				// delegate fields
				form.on(options.validationEventTrigger, "["+options.validateAttribute+"*=validate]:not([type=checkbox]):not([type=radio]):not(.datepicker)", methods._onFieldEvent);
				form.on("click", "["+options.validateAttribute+"*=validate][type=checkbox],["+options.validateAttribute+"*=validate][type=radio]", methods._onFieldEvent);
				form.on(options.validationEventTrigger,"["+options.validateAttribute+"*=validate][class*=datepicker]", {"delay": 300}, methods._onFieldEvent);
			}
			if (options.autoPositionUpdate) {
				$(window).bind("resize", {
					"noAnimation": true,
					"formElem": form
				}, methods.updatePromptsPosition);
			}
			form.on("click","a[data-validation-engine-skip], a[class*='validate-skip'], button[data-validation-engine-skip], button[class*='validate-skip'], input[data-validation-engine-skip], input[class*='validate-skip']", methods._submitButtonClick);
			form.removeData('jqv_submitButton');

			// bind form.submit
			form.on("submit", methods._onSubmitEvent);
			return this;
		},
		/**
		* Unregisters any bindings that may point to jQuery.validaitonEngine
		*/
		detach: function() {

			var form = this;
			var options = form.data('jqv');

			// unbind fields
			form.find("["+options.validateAttribute+"*=validate]").not("[type=checkbox]").off(options.validationEventTrigger, methods._onFieldEvent);
			form.find("["+options.validateAttribute+"*=validate][type=checkbox],[class*=validate][type=radio]").off("click", methods._onFieldEvent);

			// unbind form.submit
			form.off("submit", methods._onSubmitEvent);
			form.removeData('jqv');
            
			form.off("click", "a[data-validation-engine-skip], a[class*='validate-skip'], button[data-validation-engine-skip], button[class*='validate-skip'], input[data-validation-engine-skip], input[class*='validate-skip']", methods._submitButtonClick);
			form.removeData('jqv_submitButton');

			if (options.autoPositionUpdate)
				$(window).off("resize", methods.updatePromptsPosition);

			return this;
		},
		/**
		* Validates either a form or a list of fields, shows prompts accordingly.
		* Note: There is no ajax form validation with this method, only field ajax validation are evaluated
		*
		* @return true if the form validates, false if it fails
		*/
		validate: function() {
			var element = $(this);
			var valid = null;

			if (element.is("form") || element.hasClass("validationEngineContainer")) {
				if (element.hasClass('validating')) {
					// form is already validating.
					// Should abort old validation and start new one. I don't know how to implement it.
					return false;
				} else {				
					element.addClass('validating');
					var options = element.data('jqv');
					var valid = methods._validateFields(this);

					// If the form doesn't validate, clear the 'validating' class before the user has a chance to submit again
					setTimeout(function(){
						element.removeClass('validating');
					}, 100);
					if (valid && options.onSuccess) {
						options.onSuccess();
					} else if (!valid && options.onFailure) {
						options.onFailure();
					}
				}
			} else if (element.is('form') || element.hasClass('validationEngineContainer')) {
				element.removeClass('validating');
			} else {
				// field validation
				var form = element.closest('form, .validationEngineContainer'),
					options = (form.data('jqv')) ? form.data('jqv') : $.validationEngine.defaults,
					valid = methods._validateField(element, options);

				if (valid && options.onFieldSuccess)
					options.onFieldSuccess();
				else if (options.onFieldFailure && options.InvalidFields.length > 0) {
					options.onFieldFailure();
				}
			}
			if(options.onValidationComplete) {
				// !! ensures that an undefined return is interpreted as return false but allows a onValidationComplete() to possibly return true and have form continue processing
				return !!options.onValidationComplete(form, valid);
			}
			return valid;
		},
		/**
		*  Redraw prompts position, useful when you change the DOM state when validating
		*/
		updatePromptsPosition: function(event) {

			if (event && this == window) {
				var form = event.data.formElem;
				var noAnimation = event.data.noAnimation;
			}
			else
				var form = $(this.closest('form, .validationEngineContainer'));

			var options = form.data('jqv');
			// No option, take default one
			form.find('['+options.validateAttribute+'*=validate]').not(":disabled").each(function(){
				var field = $(this);
				if (options.prettySelect && field.is(":hidden"))
				  field = form.find("#" + options.usePrefix + field.attr('id') + options.useSuffix);
				var prompt = methods._getPrompt(field);
				var promptText = $(prompt).find(".formErrorContent").html();

				if(prompt)
					methods._updatePrompt(field, $(prompt), promptText, undefined, false, options, noAnimation);
			});
			return this;
		},
		/**
		* Displays a prompt on a element.
		* Note that the element needs an id!
		*
		* @param {String} promptText html text to display type
		* @param {String} type the type of bubble: 'pass' (green), 'load' (black) anything else (red)
		* @param {String} possible values topLeft, topRight, bottomLeft, centerRight, bottomRight
		*/
		showPrompt: function(promptText, type, promptPosition, showArrow) {
			var form = this.closest('form, .validationEngineContainer');
			var options = form.data('jqv');
			// No option, take default one
			if(!options)
				options = methods._saveOptions(this, options);
			if(promptPosition)
				options.promptPosition=promptPosition;
			options.showArrow = showArrow==true;

			methods._showPrompt(this, promptText, type, false, options);
			return this;
		},
		/**
		* Closes form error prompts, CAN be invidual
		*/
		hide: function() {
			 var form = $(this).closest('form, .validationEngineContainer');
			 var options = form.data('jqv');
			 var fadeDuration = (options && options.fadeDuration) ? options.fadeDuration : 0.3;
			 var closingtag;
			 
			 if($(this).is("form") || $(this).hasClass("validationEngineContainer")) {
				 closingtag = "parentForm"+methods._getClassName($(this).attr("id"));
			 } else {
				 closingtag = methods._getClassName($(this).attr("id")) +"formError";
			 }
			 $('.'+closingtag).fadeTo(fadeDuration, 0.3, function() {
				 $(this).parent('.formErrorOuter').remove();
				 $(this).remove();
			 });
			 return this;
		 },
		 /**
		 * Closes all error prompts on the page
		 */
		 hideAll: function() {

			 var form = this;
			 var options = form.data('jqv');
			 var duration = options ? options.fadeDuration:300;
			 $('.formError').fadeTo(duration, 300, function() {
				 $(this).parent('.formErrorOuter').remove();
				 $(this).remove();
			 });
			 return this;
		 },
		/**
		* Typically called when user exists a field using tab or a mouse click, triggers a field
		* validation
		*/
		_onFieldEvent: function(event) {
			var field = $(this);
			var form = field.closest('form, .validationEngineContainer');
			var options = form.data('jqv');
			options.eventTrigger = "field";
			// validate the current field
			window.setTimeout(function() {
				methods._validateField(field, options);
				if (options.InvalidFields.length == 0 && options.onFieldSuccess) {
					options.onFieldSuccess();
				} else if (options.InvalidFields.length > 0 && options.onFieldFailure) {
					options.onFieldFailure();
				}
			}, (event.data) ? event.data.delay : 0);

		},
		/**
		* Called when the form is submited, shows prompts accordingly
		*
		* @param {jqObject}
		*            form
		* @return false if form submission needs to be cancelled
		*/
		_onSubmitEvent: function() {
			var form = $(this);
			var options = form.data('jqv');
			
			//check if it is trigger from skipped button
			if (form.data("jqv_submitButton")){
				var submitButton = $("#" + form.data("jqv_submitButton"));
				if (submitButton){
					if (submitButton.length > 0){
						if (submitButton.hasClass("validate-skip") || submitButton.attr("data-validation-engine-skip") == "true")
							return true;
					}
				}
			}

			options.eventTrigger = "submit";

			// validate each field 
			// (- skip field ajax validation, not necessary IF we will perform an ajax form validation)
			var r=methods._validateFields(form);

			if (r && options.ajaxFormValidation) {
				methods._validateFormWithAjax(form, options);
				// cancel form auto-submission - process with async call onAjaxFormComplete
				return false;
			}

			if(options.onValidationComplete) {
				// !! ensures that an undefined return is interpreted as return false but allows a onValidationComplete() to possibly return true and have form continue processing
				return !!options.onValidationComplete(form, r);
			}
			return r;
		},
		/**
		* Return true if the ajax field validations passed so far
		* @param {Object} options
		* @return true, is all ajax validation passed so far (remember ajax is async)
		*/
		_checkAjaxStatus: function(options) {
			var status = true;
			$.each(options.ajaxValidCache, function(key, value) {
				if (!value) {
					status = false;
					// break the each
					return false;
				}
			});
			return status;
		},
		
		/**
		* Return true if the ajax field is validated
		* @param {String} fieldid
		* @param {Object} options
		* @return true, if validation passed, false if false or doesn't exist
		*/
		_checkAjaxFieldStatus: function(fieldid, options) {
			return options.ajaxValidCache[fieldid] == true;
		},
		/**
		* Validates form fields, shows prompts accordingly
		*
		* @param {jqObject}
		*            form
		* @param {skipAjaxFieldValidation}
		*            boolean - when set to true, ajax field validation is skipped, typically used when the submit button is clicked
		*
		* @return true if form is valid, false if not, undefined if ajax form validation is done
		*/
		_validateFields: function(form) {
			var options = form.data('jqv');

			// this variable is set to true if an error is found
			var errorFound = false;

			// Trigger hook, start validation
			form.trigger("jqv.form.validating");
			// first, evaluate status of non ajax fields
			var first_err=null;
			form.find('['+options.validateAttribute+'*=validate]').not(":disabled").each( function() {
				var field = $(this);
				var names = [];
				if ($.inArray(field.attr('name'), names) < 0) {
					errorFound |= methods._validateField(field, options);
					if (errorFound && first_err==null)
						if (field.is(":hidden") && options.prettySelect)
							first_err = field = form.find("#" + options.usePrefix + methods._jqSelector(field.attr('id')) + options.useSuffix);
						else {

							//Check if we need to adjust what element to show the prompt on
							//and and such scroll to instead
							if(field.data('jqv-prompt-at') instanceof jQuery ){
								field = field.data('jqv-prompt-at');
							} else if(field.data('jqv-prompt-at')) {
								field = $(field.data('jqv-prompt-at'));
							}
							first_err=field;
						}
					if (options.doNotShowAllErrosOnSubmit)
						return false;
					names.push(field.attr('name'));

					//if option set, stop checking validation rules after one error is found
					if(options.showOneMessage == true && errorFound){
						return false;
					}
				}
			});

			// second, check to see if all ajax calls completed ok
			// errorFound |= !methods._checkAjaxStatus(options);

			// third, check status and scroll the container accordingly
			form.trigger("jqv.form.result", [errorFound]);

			if (errorFound) {
				if (options.scroll) {
					var destination=first_err.offset().top;
					var fixleft = first_err.offset().left;

					//prompt positioning adjustment support. Usage: positionType:Xshift,Yshift (for ex.: bottomLeft:+20 or bottomLeft:-20,+10)
					var positionType=options.promptPosition;
					if (typeof(positionType)=='string' && positionType.indexOf(":")!=-1)
						positionType=positionType.substring(0,positionType.indexOf(":"));

					if (positionType!="bottomRight" && positionType!="bottomLeft") {
						var prompt_err= methods._getPrompt(first_err);
						if (prompt_err) {
							destination=prompt_err.offset().top;
						}
					}
					
					// Offset the amount the page scrolls by an amount in px to accomodate fixed elements at top of page
					if (options.scrollOffset) {
						destination -= options.scrollOffset;
					}

					// get the position of the first error, there should be at least one, no need to check this
					//var destination = form.find(".formError:not('.greenPopup'):first").offset().top;
					if (options.isOverflown) {
						var overflowDIV = $(options.overflownDIV);
						if(!overflowDIV.length) return false;
						var scrollContainerScroll = overflowDIV.scrollTop();
						var scrollContainerPos = -parseInt(overflowDIV.offset().top);

						destination += scrollContainerScroll + scrollContainerPos - 5;
						var scrollContainer = $(options.overflownDIV + ":not(:animated)");

						scrollContainer.animate({ scrollTop: destination }, 1100, function(){
							if(options.focusFirstField) first_err.focus();
						});

					} else {
						$("html, body").animate({
							scrollTop: destination
						}, 1100, function(){
							if(options.focusFirstField) first_err.focus();
						});
						$("html, body").animate({scrollLeft: fixleft},1100)
					}

				} else if(options.focusFirstField)
					first_err.focus();
				return false;
			}
			return true;
		},
		/**
		* This method is called to perform an ajax form validation.
		* During this process all the (field, value) pairs are sent to the server which returns a list of invalid fields or true
		*
		* @param {jqObject} form
		* @param {Map} options
		*/
		_validateFormWithAjax: function(form, options) {

			var data = form.serialize();
									var type = (options.ajaxFormValidationMethod) ? options.ajaxFormValidationMethod : "GET";
			var url = (options.ajaxFormValidationURL) ? options.ajaxFormValidationURL : form.attr("action");
									var dataType = (options.dataType) ? options.dataType : "json";
			$.ajax({
				type: type,
				url: url,
				cache: false,
				dataType: dataType,
				data: data,
				form: form,
				methods: methods,
				options: options,
				beforeSend: function() {
					return options.onBeforeAjaxFormValidation(form, options);
				},
				error: function(data, transport) {
					methods._ajaxError(data, transport);
				},
				success: function(json) {
					if ((dataType == "json") && (json !== true)) {
						// getting to this case doesn't necessary means that the form is invalid
						// the server may return green or closing prompt actions
						// this flag helps figuring it out
						var errorInForm=false;
						for (var i = 0; i < json.length; i++) {
							var value = json[i];

							var errorFieldId = value[0];
							var errorField = $($("#" + errorFieldId)[0]);

							// make sure we found the element
							if (errorField.length == 1) {

								// promptText or selector
								var msg = value[2];
								// if the field is valid
								if (value[1] == true) {

									if (msg == ""  || !msg){
										// if for some reason, status==true and error="", just close the prompt
										methods._closePrompt(errorField);
									} else {
										// the field is valid, but we are displaying a green prompt
										if (options.allrules[msg]) {
											var txt = options.allrules[msg].alertTextOk;
											if (txt)
												msg = txt;
										}
										if (options.showPrompts) methods._showPrompt(errorField, msg, "pass", false, options, true);
									}
								} else {
									// the field is invalid, show the red error prompt
									errorInForm|=true;
									if (options.allrules[msg]) {
										var txt = options.allrules[msg].alertText;
										if (txt)
											msg = txt;
									}
									if(options.showPrompts) methods._showPrompt(errorField, msg, "", false, options, true);
								}
							}
						}
						options.onAjaxFormComplete(!errorInForm, form, json, options);
					} else
						options.onAjaxFormComplete(true, form, json, options);

				}
			});

		},
		/**
		* Validates field, shows prompts accordingly
		*
		* @param {jqObject}
		*            field
		* @param {Array[String]}
		*            field's validation rules
		* @param {Map}
		*            user options
		* @return false if field is valid (It is inversed for *fields*, it return false on validate and true on errors.)
		*/
		_validateField: function(field, options, skipAjaxValidation) {
			if (!field.attr("id")) {
				field.attr("id", "form-validation-field-" + $.validationEngine.fieldIdCounter);
				++$.validationEngine.fieldIdCounter;
			}

           if (!options.validateNonVisibleFields && (field.is(":hidden") && !options.prettySelect || field.parent().is(":hidden")))
				return false;

			var rulesParsing = field.attr(options.validateAttribute);
			var getRules = /validate\[(.*)\]/.exec(rulesParsing);

			if (!getRules)
				return false;
			var str = getRules[1];
			var rules = str.split(/\[|,|\]/);

			// true if we ran the ajax validation, tells the logic to stop messing with prompts
			var isAjaxValidator = false;
			var fieldName = field.attr("name");
			var promptText = "";
			var promptType = "";
			var required = false;
			var limitErrors = false;
			options.isError = false;
			options.showArrow = true;
			
			// If the programmer wants to limit the amount of error messages per field,
			if (options.maxErrorsPerField > 0) {
				limitErrors = true;
			}

			var form = $(field.closest("form, .validationEngineContainer"));
			// Fix for adding spaces in the rules
			for (var i = 0; i < rules.length; i++) {
				rules[i] = rules[i].replace(" ", "");
				// Remove any parsing errors
				if (rules[i] === '') {
					delete rules[i];
				}
			}

			for (var i = 0, field_errors = 0; i < rules.length; i++) {
				
				// If we are limiting errors, and have hit the max, break
				if (limitErrors && field_errors >= options.maxErrorsPerField) {
					// If we haven't hit a required yet, check to see if there is one in the validation rules for this
					// field and that it's index is greater or equal to our current index
					if (!required) {
						var have_required = $.inArray('required', rules);
						required = (have_required != -1 &&  have_required >= i);
					}
					break;
				}
				
				
				var errorMsg = undefined;
				switch (rules[i]) {

					case "required":
						required = true;
						errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._required);
						break;
					case "custom":
						errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._custom);
						break;
					case "groupRequired":
						// Check is its the first of group, if not, reload validation with first field
						// AND continue normal validation on present field
						var classGroup = "["+options.validateAttribute+"*=" +rules[i + 1] +"]";
						var firstOfGroup = form.find(classGroup).eq(0);
						if(firstOfGroup[0] != field[0]){

							methods._validateField(firstOfGroup, options, skipAjaxValidation); 
							options.showArrow = true;

						}
						errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._groupRequired);
						if(errorMsg)  required = true;
						options.showArrow = false;
						break;
					case "ajax":
						// AJAX defaults to returning it's loading message
						errorMsg = methods._ajax(field, rules, i, options);
						if (errorMsg) {
							promptType = "load";
						}
						break;
					case "minSize":
						errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._minSize);
						break;
					case "maxSize":
						errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._maxSize);
						break;
					case "min":
						errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._min);
						break;
					case "max":
						errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._max);
						break;
					case "past":
						errorMsg = methods._getErrorMessage(form, field,rules[i], rules, i, options, methods._past);
						break;
					case "future":
						errorMsg = methods._getErrorMessage(form, field,rules[i], rules, i, options, methods._future);
						break;
					case "dateRange":
						var classGroup = "["+options.validateAttribute+"*=" + rules[i + 1] + "]";
						options.firstOfGroup = form.find(classGroup).eq(0);
						options.secondOfGroup = form.find(classGroup).eq(1);

						//if one entry out of the pair has value then proceed to run through validation
						if (options.firstOfGroup[0].value || options.secondOfGroup[0].value) {
							errorMsg = methods._getErrorMessage(form, field,rules[i], rules, i, options, methods._dateRange);
						}
						if (errorMsg) required = true;
						options.showArrow = false;
						break;

					case "dateTimeRange":
						var classGroup = "["+options.validateAttribute+"*=" + rules[i + 1] + "]";
						options.firstOfGroup = form.find(classGroup).eq(0);
						options.secondOfGroup = form.find(classGroup).eq(1);

						//if one entry out of the pair has value then proceed to run through validation
						if (options.firstOfGroup[0].value || options.secondOfGroup[0].value) {
							errorMsg = methods._getErrorMessage(form, field,rules[i], rules, i, options, methods._dateTimeRange);
						}
						if (errorMsg) required = true;
						options.showArrow = false;
						break;
					case "maxCheckbox":
						field = $(form.find("input[name='" + fieldName + "']"));
						errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._maxCheckbox);
						break;
					case "minCheckbox":
						field = $(form.find("input[name='" + fieldName + "']"));
						errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._minCheckbox);
						break;
					case "equals":
						errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._equals);
						break;
					case "funcCall":
						errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._funcCall);
						break;
					case "creditCard":
						errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._creditCard);
						break;
					case "condRequired":
						errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._condRequired);
						if (errorMsg !== undefined) {
							required = true;
						}
						break;

					default:
				}
				
				var end_validation = false;
				
				// If we were passed back an message object, check what the status was to determine what to do
				if (typeof errorMsg == "object") {
					switch (errorMsg.status) {
						case "_break":
							end_validation = true;
							break;
						// If we have an error message, set errorMsg to the error message
						case "_error":
							errorMsg = errorMsg.message;
							break;
						// If we want to throw an error, but not show a prompt, return early with true
						case "_error_no_prompt":
							return true;
							break;
						// Anything else we continue on
						default:
							break;
					}
				}
				
				// If it has been specified that validation should end now, break
				if (end_validation) {
					break;
				}
				
				// If we have a string, that means that we have an error, so add it to the error message.
				if (typeof errorMsg == 'string') {
					promptText += errorMsg + "<br/>";
					options.isError = true;
					field_errors++;
				}	
			}
			// If the rules required is not added, an empty field is not validated
			if(!required && !(field.val()) && field.val().length < 1) options.isError = false;

			// Hack for radio/checkbox group button, the validation go into the
			// first radio/checkbox of the group
			var fieldType = field.prop("type");
			var positionType=field.data("promptPosition") || options.promptPosition;

			if ((fieldType == "radio" || fieldType == "checkbox") && form.find("input[name='" + fieldName + "']").size() > 1) {
				if(positionType === 'inline') {
					field = $(form.find("input[name='" + fieldName + "'][type!=hidden]:last"));
				} else {
				field = $(form.find("input[name='" + fieldName + "'][type!=hidden]:first"));
				}
				options.showArrow = false;
			}

			if(field.is(":hidden") && options.prettySelect) {
				field = form.find("#" + options.usePrefix + methods._jqSelector(field.attr('id')) + options.useSuffix);
			}

			if (options.isError && options.showPrompts){
				methods._showPrompt(field, promptText, promptType, false, options);
			}else{
				if (!isAjaxValidator) methods._closePrompt(field);
			}

			if (!isAjaxValidator) {
				field.trigger("jqv.field.result", [field, options.isError, promptText]);
			}

			/* Record error */
			var errindex = $.inArray(field[0], options.InvalidFields);
			if (errindex == -1) {
				if (options.isError)
				options.InvalidFields.push(field[0]);
			} else if (!options.isError) {
				options.InvalidFields.splice(errindex, 1);
			}
				
			methods._handleStatusCssClasses(field, options);
	
			/* run callback function for each field */
			if (options.isError && options.onFieldFailure)
				options.onFieldFailure(field);

			if (!options.isError && options.onFieldSuccess)
				options.onFieldSuccess(field);

			return options.isError;
		},
		/**
		* Handling css classes of fields indicating result of validation 
		*
		* @param {jqObject}
		*            field
		* @param {Array[String]}
		*            field's validation rules            
		* @private
		*/
		_handleStatusCssClasses: function(field, options) {
			/* remove all classes */
			if(options.addSuccessCssClassToField)
				field.removeClass(options.addSuccessCssClassToField);
			
			if(options.addFailureCssClassToField)
				field.removeClass(options.addFailureCssClassToField);
			
			/* Add classes */
			if (options.addSuccessCssClassToField && !options.isError)
				field.addClass(options.addSuccessCssClassToField);
			
			if (options.addFailureCssClassToField && options.isError)
				field.addClass(options.addFailureCssClassToField);		
		},
		
		 /********************
		  * _getErrorMessage
		  *
		  * @param form
		  * @param field
		  * @param rule
		  * @param rules
		  * @param i
		  * @param options
		  * @param originalValidationMethod
		  * @return {*}
		  * @private
		  */
		 _getErrorMessage:function (form, field, rule, rules, i, options, originalValidationMethod) {
			 // If we are using the custon validation type, build the index for the rule.
			 // Otherwise if we are doing a function call, make the call and return the object
			 // that is passed back.
	 		 var rule_index = jQuery.inArray(rule, rules);
			 if (rule === "custom" || rule === "funcCall") {
				 var custom_validation_type = rules[rule_index + 1];
				 rule = rule + "[" + custom_validation_type + "]";
				 // Delete the rule from the rules array so that it doesn't try to call the
			    // same rule over again
			    delete(rules[rule_index]);
			 }
			 // Change the rule to the composite rule, if it was different from the original
			 var alteredRule = rule;


			 var element_classes = (field.attr("data-validation-engine")) ? field.attr("data-validation-engine") : field.attr("class");
			 var element_classes_array = element_classes.split(" ");

			 // Call the original validation method. If we are dealing with dates or checkboxes, also pass the form
			 var errorMsg;
			 if (rule == "future" || rule == "past"  || rule == "maxCheckbox" || rule == "minCheckbox") {
				 errorMsg = originalValidationMethod(form, field, rules, i, options);
			 } else {
				 errorMsg = originalValidationMethod(field, rules, i, options);
			 }

			 // If the original validation method returned an error and we have a custom error message,
			 // return the custom message instead. Otherwise return the original error message.
			 if (errorMsg != undefined) {
				 var custom_message = methods._getCustomErrorMessage($(field), element_classes_array, alteredRule, options);
				 if (custom_message) errorMsg = custom_message;
			 }
			 return errorMsg;

		 },
		 _getCustomErrorMessage:function (field, classes, rule, options) {
			var custom_message = false;
			var validityProp = /^custom\[.*\]$/.test(rule) ? methods._validityProp["custom"] : methods._validityProp[rule];
			 // If there is a validityProp for this rule, check to see if the field has an attribute for it
			if (validityProp != undefined) {
				custom_message = field.attr("data-errormessage-"+validityProp);
				// If there was an error message for it, return the message
				if (custom_message != undefined) 
					return custom_message;
			}
			custom_message = field.attr("data-errormessage");
			 // If there is an inline custom error message, return it
			if (custom_message != undefined) 
				return custom_message;
			var id = '#' + field.attr("id");
			// If we have custom messages for the element's id, get the message for the rule from the id.
			// Otherwise, if we have custom messages for the element's classes, use the first class message we find instead.
			if (typeof options.custom_error_messages[id] != "undefined" &&
				typeof options.custom_error_messages[id][rule] != "undefined" ) {
						  custom_message = options.custom_error_messages[id][rule]['message'];
			} else if (classes.length > 0) {
				for (var i = 0; i < classes.length && classes.length > 0; i++) {
					 var element_class = "." + classes[i];
					if (typeof options.custom_error_messages[element_class] != "undefined" &&
						typeof options.custom_error_messages[element_class][rule] != "undefined") {
							custom_message = options.custom_error_messages[element_class][rule]['message'];
							break;
					}
				}
			}
			if (!custom_message &&
				typeof options.custom_error_messages[rule] != "undefined" &&
				typeof options.custom_error_messages[rule]['message'] != "undefined"){
					 custom_message = options.custom_error_messages[rule]['message'];
			 }
			 return custom_message;
		 },
		 _validityProp: {
			 "required": "value-missing",
			 "custom": "custom-error",
			 "groupRequired": "value-missing",
			 "ajax": "custom-error",
			 "minSize": "range-underflow",
			 "maxSize": "range-overflow",
			 "min": "range-underflow",
			 "max": "range-overflow",
			 "past": "type-mismatch",
			 "future": "type-mismatch",
			 "dateRange": "type-mismatch",
			 "dateTimeRange": "type-mismatch",
			 "maxCheckbox": "range-overflow",
			 "minCheckbox": "range-underflow",
			 "equals": "pattern-mismatch",
			 "funcCall": "custom-error",
			 "creditCard": "pattern-mismatch",
			 "condRequired": "value-missing"
		 },
		/**
		* Required validation
		*
		* @param {jqObject} field
		* @param {Array[String]} rules
		* @param {int} i rules index
		* @param {Map}
		*            user options
		* @param {bool} condRequired flag when method is used for internal purpose in condRequired check
		* @return an error string if validation failed
		*/
		_required: function(field, rules, i, options, condRequired) {
			switch (field.prop("type")) {
				case "text":
				case "password":
				case "textarea":
				case "file":
				case "select-one":
				case "select-multiple":
				default:
					var field_val      = $.trim( field.val()                               );
					var dv_placeholder = $.trim( field.attr("data-validation-placeholder") );
					var placeholder    = $.trim( field.attr("placeholder")                 );
					if (
						   ( !field_val                                    )
						|| ( dv_placeholder && field_val == dv_placeholder )
						|| ( placeholder    && field_val == placeholder    )
					) {
						return options.allrules[rules[i]].alertText;
					}
					break;
				case "radio":
				case "checkbox":
					// new validation style to only check dependent field
					if (condRequired) {
						if (!field.attr('checked')) {
							return options.allrules[rules[i]].alertTextCheckboxMultiple;
						}
						break;
					}
					// old validation style
					var form = field.closest("form, .validationEngineContainer");
					var name = field.attr("name");
					if (form.find("input[name='" + name + "']:checked").size() == 0) {
						if (form.find("input[name='" + name + "']:visible").size() == 1)
							return options.allrules[rules[i]].alertTextCheckboxe;
						else
							return options.allrules[rules[i]].alertTextCheckboxMultiple;
					}
					break;
			}
		},
		/**
		* Validate that 1 from the group field is required
		*
		* @param {jqObject} field
		* @param {Array[String]} rules
		* @param {int} i rules index
		* @param {Map}
		*            user options
		* @return an error string if validation failed
		*/
		_groupRequired: function(field, rules, i, options) {
			var classGroup = "["+options.validateAttribute+"*=" +rules[i + 1] +"]";
			var isValid = false;
			// Check all fields from the group
			field.closest("form, .validationEngineContainer").find(classGroup).each(function(){
				if(!methods._required($(this), rules, i, options)){
					isValid = true;
					return false;
				}
			}); 

			if(!isValid) {
		  return options.allrules[rules[i]].alertText;
		}
		},
		/**
		* Validate rules
		*
		* @param {jqObject} field
		* @param {Array[String]} rules
		* @param {int} i rules index
		* @param {Map}
		*            user options
		* @return an error string if validation failed
		*/
		_custom: function(field, rules, i, options) {
			var customRule = rules[i + 1];
			var rule = options.allrules[customRule];
			var fn;
			if(!rule) {
				alert("jqv:custom rule not found - "+customRule);
				return;
			}
			
			if(rule["regex"]) {
				 var ex=rule.regex;
					if(!ex) {
						alert("jqv:custom regex not found - "+customRule);
						return;
					}
					var pattern = new RegExp(ex);

					if (!pattern.test(field.val())) return options.allrules[customRule].alertText;
					
			} else if(rule["func"]) {
				fn = rule["func"]; 
				 
				if (typeof(fn) !== "function") {
					alert("jqv:custom parameter 'function' is no function - "+customRule);
						return;
				}
				 
				if (!fn(field, rules, i, options))
					return options.allrules[customRule].alertText;
			} else {
				alert("jqv:custom type not allowed "+customRule);
					return;
			}
		},
		/**
		* Validate custom function outside of the engine scope
		*
		* @param {jqObject} field
		* @param {Array[String]} rules
		* @param {int} i rules index
		* @param {Map}
		*            user options
		* @return an error string if validation failed
		*/
		_funcCall: function(field, rules, i, options) {
			var functionName = rules[i + 1];
			var fn;
			if(functionName.indexOf('.') >-1)
			{
				var namespaces = functionName.split('.');
				var scope = window;
				while(namespaces.length)
				{
					scope = scope[namespaces.shift()];
				}
				fn = scope;
			}
			else
				fn = window[functionName] || options.customFunctions[functionName];
			if (typeof(fn) == 'function')
				return fn(field, rules, i, options);

		},
		/**
		* Field match
		*
		* @param {jqObject} field
		* @param {Array[String]} rules
		* @param {int} i rules index
		* @param {Map}
		*            user options
		* @return an error string if validation failed
		*/
		_equals: function(field, rules, i, options) {
			var equalsField = rules[i + 1];

			if (field.val() != $("#" + equalsField).val())
				return options.allrules.equals.alertText;
		},
		/**
		* Check the maximum size (in characters)
		*
		* @param {jqObject} field
		* @param {Array[String]} rules
		* @param {int} i rules index
		* @param {Map}
		*            user options
		* @return an error string if validation failed
		*/
		_maxSize: function(field, rules, i, options) {
			var max = rules[i + 1];
			var len = field.val().length;

			if (len > max) {
				var rule = options.allrules.maxSize;
				return rule.alertText + max + rule.alertText2;
			}
		},
		/**
		* Check the minimum size (in characters)
		*
		* @param {jqObject} field
		* @param {Array[String]} rules
		* @param {int} i rules index
		* @param {Map}
		*            user options
		* @return an error string if validation failed
		*/
		_minSize: function(field, rules, i, options) {
			var min = rules[i + 1];
			var len = field.val().length;

			if (len < min) {
				var rule = options.allrules.minSize;
				return rule.alertText + min + rule.alertText2;
			}
		},
		/**
		* Check number minimum value
		*
		* @param {jqObject} field
		* @param {Array[String]} rules
		* @param {int} i rules index
		* @param {Map}
		*            user options
		* @return an error string if validation failed
		*/
		_min: function(field, rules, i, options) {
			var min = parseFloat(rules[i + 1]);
			var len = parseFloat(field.val());

			if (len < min) {
				var rule = options.allrules.min;
				if (rule.alertText2) return rule.alertText + min + rule.alertText2;
				return rule.alertText + min;
			}
		},
		/**
		* Check number maximum value
		*
		* @param {jqObject} field
		* @param {Array[String]} rules
		* @param {int} i rules index
		* @param {Map}
		*            user options
		* @return an error string if validation failed
		*/
		_max: function(field, rules, i, options) {
			var max = parseFloat(rules[i + 1]);
			var len = parseFloat(field.val());

			if (len >max ) {
				var rule = options.allrules.max;
				if (rule.alertText2) return rule.alertText + max + rule.alertText2;
				//orefalo: to review, also do the translations
				return rule.alertText + max;
			}
		},
		/**
		* Checks date is in the past
		*
		* @param {jqObject} field
		* @param {Array[String]} rules
		* @param {int} i rules index
		* @param {Map}
		*            user options
		* @return an error string if validation failed
		*/
		_past: function(form, field, rules, i, options) {

			var p=rules[i + 1];
			var fieldAlt = $(form.find("input[name='" + p.replace(/^#+/, '') + "']"));
			var pdate;

			if (p.toLowerCase() == "now") {
				pdate = new Date();
			} else if (undefined != fieldAlt.val()) {
				if (fieldAlt.is(":disabled"))
					return;
				pdate = methods._parseDate(fieldAlt.val());
			} else {
				pdate = methods._parseDate(p);
			}
			var vdate = methods._parseDate(field.val());

			if (vdate > pdate ) {
				var rule = options.allrules.past;
				if (rule.alertText2) return rule.alertText + methods._dateToString(pdate) + rule.alertText2;
				return rule.alertText + methods._dateToString(pdate);
			}
		},
		/**
		* Checks date is in the future
		*
		* @param {jqObject} field
		* @param {Array[String]} rules
		* @param {int} i rules index
		* @param {Map}
		*            user options
		* @return an error string if validation failed
		*/
		_future: function(form, field, rules, i, options) {

			var p=rules[i + 1];
			var fieldAlt = $(form.find("input[name='" + p.replace(/^#+/, '') + "']"));
			var pdate;

			if (p.toLowerCase() == "now") {
				pdate = new Date();
			} else if (undefined != fieldAlt.val()) {
				if (fieldAlt.is(":disabled"))
					return;
				pdate = methods._parseDate(fieldAlt.val());
			} else {
				pdate = methods._parseDate(p);
			}
			var vdate = methods._parseDate(field.val());

			if (vdate < pdate ) {
				var rule = options.allrules.future;
				if (rule.alertText2)
					return rule.alertText + methods._dateToString(pdate) + rule.alertText2;
				return rule.alertText + methods._dateToString(pdate);
			}
		},
		/**
		* Checks if valid date
		*
		* @param {string} date string
		* @return a bool based on determination of valid date
		*/
		_isDate: function (value) {
		    //var dateRegEx = new RegExp(/^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])$|^(?:(?:(?:0?[13578]|1[02])(\/|-)31)|(?:(?:0?[1,3-9]|1[0-2])(\/|-)(?:29|30)))(\/|-)(?:[1-9]\d\d\d|\d[1-9]\d\d|\d\d[1-9]\d|\d\d\d[1-9])$|^(?:(?:0?[1-9]|1[0-2])(\/|-)(?:0?[1-9]|1\d|2[0-8]))(\/|-)(?:[1-9]\d\d\d|\d[1-9]\d\d|\d\d[1-9]\d|\d\d\d[1-9])$|^(0?2(\/|-)29)(\/|-)(?:(?:0[48]00|[13579][26]00|[2468][048]00)|(?:\d\d)?(?:0[48]|[2468][048]|[13579][26]))$/);
		    var dateRegEx = new RegExp("^((0?[1-9]|1[012])[- /.](0?[1-9]|[12][0-9]|3[01])[- /.](19|20)?[0-9]{2})*$");
			return dateRegEx.test(value);
		},
		/**
		* Checks if valid date time
		*
		* @param {string} date string
		* @return a bool based on determination of valid date time
		*/
		_isDateTime: function (value){
			var dateTimeRegEx = new RegExp(/^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])\s+(1[012]|0?[1-9]){1}:(0?[1-5]|[0-6][0-9]){1}:(0?[0-6]|[0-6][0-9]){1}\s+(am|pm|AM|PM){1}$|^(?:(?:(?:0?[13578]|1[02])(\/|-)31)|(?:(?:0?[1,3-9]|1[0-2])(\/|-)(?:29|30)))(\/|-)(?:[1-9]\d\d\d|\d[1-9]\d\d|\d\d[1-9]\d|\d\d\d[1-9])$|^((1[012]|0?[1-9]){1}\/(0?[1-9]|[12][0-9]|3[01]){1}\/\d{2,4}\s+(1[012]|0?[1-9]){1}:(0?[1-5]|[0-6][0-9]){1}:(0?[0-6]|[0-6][0-9]){1}\s+(am|pm|AM|PM){1})$/);
			return dateTimeRegEx.test(value);
		},
		//Checks if the start date is before the end date
		//returns true if end is later than start
		_dateCompare: function (start, end) {
			return (new Date(start.toString()) < new Date(end.toString()));
		},
		/**
		* Checks date range
		*
		* @param {jqObject} first field name
		* @param {jqObject} second field name
		* @return an error string if validation failed
		*/
		_dateRange: function (field, rules, i, options) {
			//are not both populated
			if ((!options.firstOfGroup[0].value && options.secondOfGroup[0].value) || (options.firstOfGroup[0].value && !options.secondOfGroup[0].value)) {
				return options.allrules[rules[i]].alertText + options.allrules[rules[i]].alertText2;
			}

			//are not both dates
			if (!methods._isDate(options.firstOfGroup[0].value) || !methods._isDate(options.secondOfGroup[0].value)) {
				return options.allrules[rules[i]].alertText + options.allrules[rules[i]].alertText2;
			}

			//are both dates but range is off
			if (!methods._dateCompare(options.firstOfGroup[0].value, options.secondOfGroup[0].value)) {
				return options.allrules[rules[i]].alertText + options.allrules[rules[i]].alertText2;
			}
		},
		/**
		* Checks date time range
		*
		* @param {jqObject} first field name
		* @param {jqObject} second field name
		* @return an error string if validation failed
		*/
		_dateTimeRange: function (field, rules, i, options) {
			//are not both populated
			if ((!options.firstOfGroup[0].value && options.secondOfGroup[0].value) || (options.firstOfGroup[0].value && !options.secondOfGroup[0].value)) {
				return options.allrules[rules[i]].alertText + options.allrules[rules[i]].alertText2;
			}
			//are not both dates
			if (!methods._isDateTime(options.firstOfGroup[0].value) || !methods._isDateTime(options.secondOfGroup[0].value)) {
				return options.allrules[rules[i]].alertText + options.allrules[rules[i]].alertText2;
			}
			//are both dates but range is off
			if (!methods._dateCompare(options.firstOfGroup[0].value, options.secondOfGroup[0].value)) {
				return options.allrules[rules[i]].alertText + options.allrules[rules[i]].alertText2;
			}
		},
		/**
		* Max number of checkbox selected
		*
		* @param {jqObject} field
		* @param {Array[String]} rules
		* @param {int} i rules index
		* @param {Map}
		*            user options
		* @return an error string if validation failed
		*/
		_maxCheckbox: function(form, field, rules, i, options) {

			var nbCheck = rules[i + 1];
			var groupname = field.attr("name");
			var groupSize = form.find("input[name='" + groupname + "']:checked").size();
			if (groupSize > nbCheck) {
				options.showArrow = false;
				if (options.allrules.maxCheckbox.alertText2)
					 return options.allrules.maxCheckbox.alertText + " " + nbCheck + " " + options.allrules.maxCheckbox.alertText2;
				return options.allrules.maxCheckbox.alertText;
			}
		},
		/**
		* Min number of checkbox selected
		*
		* @param {jqObject} field
		* @param {Array[String]} rules
		* @param {int} i rules index
		* @param {Map}
		*            user options
		* @return an error string if validation failed
		*/
		_minCheckbox: function(form, field, rules, i, options) {

			var nbCheck = rules[i + 1];
			var groupname = field.attr("name");
			var groupSize = form.find("input[name='" + groupname + "']:checked").size();
			if (groupSize < nbCheck) {
				options.showArrow = false;
				return options.allrules.minCheckbox.alertText + " " + nbCheck + " " + options.allrules.minCheckbox.alertText2;
			}
		},
		/**
		* Checks that it is a valid credit card number according to the
		* Luhn checksum algorithm.
		*
		* @param {jqObject} field
		* @param {Array[String]} rules
		* @param {int} i rules index
		* @param {Map}
		*            user options
		* @return an error string if validation failed
		*/
		_creditCard: function(field, rules, i, options) {
			//spaces and dashes may be valid characters, but must be stripped to calculate the checksum.
			var valid = false, cardNumber = field.val().replace(/ +/g, '').replace(/-+/g, '');

			var numDigits = cardNumber.length;
			if (numDigits >= 14 && numDigits <= 16 && parseInt(cardNumber) > 0) {

				var sum = 0, i = numDigits - 1, pos = 1, digit, luhn = new String();
				do {
					digit = parseInt(cardNumber.charAt(i));
					luhn += (pos++ % 2 == 0) ? digit * 2 : digit;
				} while (--i >= 0)

				for (i = 0; i < luhn.length; i++) {
					sum += parseInt(luhn.charAt(i));
				}
				valid = sum % 10 == 0;
			}
			if (!valid) return options.allrules.creditCard.alertText;
		},
		/**
		* Ajax field validation
		*
		* @param {jqObject} field
		* @param {Array[String]} rules
		* @param {int} i rules index
		* @param {Map}
		*            user options
		* @return nothing! the ajax validator handles the prompts itself
		*/
		 _ajax: function(field, rules, i, options) {

			 var errorSelector = rules[i + 1];
			 var rule = options.allrules[errorSelector];
			 var extraData = rule.extraData;
			 var extraDataDynamic = rule.extraDataDynamic;
			 var data = {
				"fieldId" : field.attr("id"),
				"fieldValue" : field.val()
			 };

			 if (typeof extraData === "object") {
				$.extend(data, extraData);
			 } else if (typeof extraData === "string") {
				var tempData = extraData.split("&");
				for(var i = 0; i < tempData.length; i++) {
					var values = tempData[i].split("=");
					if (values[0] && values[0]) {
						data[values[0]] = values[1];
					}
				}
			 }

			 if (extraDataDynamic) {
				 var tmpData = [];
				 var domIds = String(extraDataDynamic).split(",");
				 for (var i = 0; i < domIds.length; i++) {
					 var id = domIds[i];
					 if ($(id).length) {
						 var inputValue = field.closest("form, .validationEngineContainer").find(id).val();
						 var keyValue = id.replace('#', '') + '=' + escape(inputValue);
						 data[id.replace('#', '')] = inputValue;
					 }
				 }
			 }
			 
			 // If a field change event triggered this we want to clear the cache for this ID
			 if (options.eventTrigger == "field") {
				delete(options.ajaxValidCache[field.attr("id")]);
			 }

			 // If there is an error or if the the field is already validated, do not re-execute AJAX
			 if (!options.isError && !methods._checkAjaxFieldStatus(field.attr("id"), options)) {
				 $.ajax({
					 type: options.ajaxFormValidationMethod,
					 url: rule.url,
					 cache: false,
					 dataType: "json",
					 data: data,
					 field: field,
					 rule: rule,
					 methods: methods,
					 options: options,
					 beforeSend: function() {},
					 error: function(data, transport) {
						 methods._ajaxError(data, transport);
					 },
					 success: function(json) {

						 // asynchronously called on success, data is the json answer from the server
						 var errorFieldId = json[0];
						 //var errorField = $($("#" + errorFieldId)[0]);
						 var errorField = $("#"+ errorFieldId).eq(0);

						 // make sure we found the element
						 if (errorField.length == 1) {
							 var status = json[1];
							 // read the optional msg from the server
							 var msg = json[2];
							 if (!status) {
								 // Houston we got a problem - display an red prompt
								 options.ajaxValidCache[errorFieldId] = false;
								 options.isError = true;

								 // resolve the msg prompt
								 if(msg) {
									 if (options.allrules[msg]) {
										 var txt = options.allrules[msg].alertText;
										 if (txt) {
											msg = txt;
							}
									 }
								 }
								 else
									msg = rule.alertText;

								 if (options.showPrompts) methods._showPrompt(errorField, msg, "", true, options);
							 } else {
								 options.ajaxValidCache[errorFieldId] = true;

								 // resolves the msg prompt
								 if(msg) {
									 if (options.allrules[msg]) {
										 var txt = options.allrules[msg].alertTextOk;
										 if (txt) {
											msg = txt;
							}
									 }
								 }
								 else
								 msg = rule.alertTextOk;

								 if (options.showPrompts) {
									 // see if we should display a green prompt
									 if (msg)
										methods._showPrompt(errorField, msg, "pass", true, options);
									 else
										methods._closePrompt(errorField);
								}
								
								 // If a submit form triggered this, we want to re-submit the form
								 if (options.eventTrigger == "submit")
									field.closest("form").submit();
							 }
						 }
						 errorField.trigger("jqv.field.result", [errorField, options.isError, msg]);
					 }
				 });
				 
				 return rule.alertTextLoad;
			 }
		 },
		/**
		* Common method to handle ajax errors
		*
		* @param {Object} data
		* @param {Object} transport
		*/
		_ajaxError: function(data, transport) {
			if(data.status == 0 && transport == null)
				alert("The page is not served from a server! ajax call failed");
			else if(typeof console != "undefined")
				console.log("Ajax error: " + data.status + " " + transport);
		},
		/**
		* date -> string
		*
		* @param {Object} date
		*/
		_dateToString: function(date) {
			return date.getFullYear()+"-"+(date.getMonth()+1)+"-"+date.getDate();
		},
		/**
		* Parses an ISO date
		* @param {String} d
		*/
		_parseDate: function(d) {

			var dateParts = d.split("-");
			if(dateParts==d)
				dateParts = d.split("/");
			if(dateParts==d) {
				dateParts = d.split(".");
				return new Date(dateParts[2], (dateParts[1] - 1), dateParts[0]);
			}
			return new Date(dateParts[0], (dateParts[1] - 1) ,dateParts[2]);
		},
		/**
		* Builds or updates a prompt with the given information
		*
		* @param {jqObject} field
		* @param {String} promptText html text to display type
		* @param {String} type the type of bubble: 'pass' (green), 'load' (black) anything else (red)
		* @param {boolean} ajaxed - use to mark fields than being validated with ajax
		* @param {Map} options user options
		*/
		 _showPrompt: function(field, promptText, type, ajaxed, options, ajaxform) {
		 	//Check if we need to adjust what element to show the prompt on
			if(field.data('jqv-prompt-at') instanceof jQuery ){
				field = field.data('jqv-prompt-at');
			} else if(field.data('jqv-prompt-at')) {
				field = $(field.data('jqv-prompt-at'));
			}

			 var prompt = methods._getPrompt(field);
			 // The ajax submit errors are not see has an error in the form,
			 // When the form errors are returned, the engine see 2 bubbles, but those are ebing closed by the engine at the same time
			 // Because no error was found befor submitting
			 if(ajaxform) prompt = false;
			 // Check that there is indded text
			 if($.trim(promptText)){ 
				 if (prompt)
					methods._updatePrompt(field, prompt, promptText, type, ajaxed, options);
				 else
					methods._buildPrompt(field, promptText, type, ajaxed, options);
			}
		 },
		/**
		* Builds and shades a prompt for the given field.
		*
		* @param {jqObject} field
		* @param {String} promptText html text to display type
		* @param {String} type the type of bubble: 'pass' (green), 'load' (black) anything else (red)
		* @param {boolean} ajaxed - use to mark fields than being validated with ajax
		* @param {Map} options user options
		*/
		_buildPrompt: function(field, promptText, type, ajaxed, options) {

			// create the prompt
			var prompt = $('<div>');
			prompt.addClass(methods._getClassName(field.attr("id")) + "formError");
			// add a class name to identify the parent form of the prompt
			prompt.addClass("parentForm"+methods._getClassName(field.closest('form, .validationEngineContainer').attr("id")));
			prompt.addClass("formError");

			switch (type) {
				case "pass":
					prompt.addClass("greenPopup");
					break;
				case "load":
					prompt.addClass("blackPopup");
					break;
				default:
					/* it has error  */
					//alert("unknown popup type:"+type);
			}
			if (ajaxed)
				prompt.addClass("ajaxed");

			// create the prompt content
			var promptContent = $('<div>').addClass("formErrorContent").html(promptText).appendTo(prompt);

			// determine position type
			var positionType=field.data("promptPosition") || options.promptPosition;

			// create the css arrow pointing at the field
			// note that there is no triangle on max-checkbox and radio
			if (options.showArrow) {
				var arrow = $('<div>').addClass("formErrorArrow");

				//prompt positioning adjustment support. Usage: positionType:Xshift,Yshift (for ex.: bottomLeft:+20 or bottomLeft:-20,+10)
				if (typeof(positionType)=='string') 
				{
					var pos=positionType.indexOf(":");
					if(pos!=-1)
						positionType=positionType.substring(0,pos);
				}

				switch (positionType) {
					case "bottomLeft":
					case "bottomRight":
						prompt.find(".formErrorContent").before(arrow);
						arrow.addClass("formErrorArrowBottom").html('<div class="line1"><!-- --></div><div class="line2"><!-- --></div><div class="line3"><!-- --></div><div class="line4"><!-- --></div><div class="line5"><!-- --></div><div class="line6"><!-- --></div><div class="line7"><!-- --></div><div class="line8"><!-- --></div><div class="line9"><!-- --></div><div class="line10"><!-- --></div>');
						break;
					case "topLeft":
					case "topRight":
						arrow.html('<div class="line10"><!-- --></div><div class="line9"><!-- --></div><div class="line8"><!-- --></div><div class="line7"><!-- --></div><div class="line6"><!-- --></div><div class="line5"><!-- --></div><div class="line4"><!-- --></div><div class="line3"><!-- --></div><div class="line2"><!-- --></div><div class="line1"><!-- --></div>');
						prompt.append(arrow);
						break;
				}
			}
			// Add custom prompt class
			if (options.addPromptClass)
				prompt.addClass(options.addPromptClass);

            // Add custom prompt class defined in element
            var requiredOverride = field.attr('data-required-class');
            if(requiredOverride !== undefined) {
                prompt.addClass(requiredOverride);
            } else {
                if(options.prettySelect) {
                    if($('#' + field.attr('id')).next().is('select')) {
                        var prettyOverrideClass = $('#' + field.attr('id').substr(options.usePrefix.length).substring(options.useSuffix.length)).attr('data-required-class');
                        if(prettyOverrideClass !== undefined) {
                            prompt.addClass(prettyOverrideClass);
                        }
                    }
                }
            }

			prompt.css({
				"opacity": 0
			});
			if(positionType === 'inline') {
				prompt.addClass("inline");
				if(typeof field.attr('data-prompt-target') !== 'undefined' && $('#'+field.attr('data-prompt-target')).length > 0) {
					prompt.appendTo($('#'+field.attr('data-prompt-target')));
				} else {
					field.after(prompt);
				}
			} else {
				field.before(prompt);				
			}
			
			var pos = methods._calculatePosition(field, prompt, options);
			prompt.css({
				'position': positionType === 'inline' ? 'relative' : 'absolute',
				"top": pos.callerTopPosition,
				"left": pos.callerleftPosition,
				"marginTop": pos.marginTopSize,
				"opacity": 0
			}).data("callerField", field);
			

			if (options.autoHidePrompt) {
				setTimeout(function(){
					prompt.animate({
						"opacity": 0
					},function(){
						prompt.closest('.formErrorOuter').remove();
						prompt.remove();
					});
				}, options.autoHideDelay);
			} 
			return prompt.animate({
				"opacity": 0.87
			});
		},
		/**
		* Updates the prompt text field - the field for which the prompt
		* @param {jqObject} field
		* @param {String} promptText html text to display type
		* @param {String} type the type of bubble: 'pass' (green), 'load' (black) anything else (red)
		* @param {boolean} ajaxed - use to mark fields than being validated with ajax
		* @param {Map} options user options
		*/
		_updatePrompt: function(field, prompt, promptText, type, ajaxed, options, noAnimation) {

			if (prompt) {
				if (typeof type !== "undefined") {
					if (type == "pass")
						prompt.addClass("greenPopup");
					else
						prompt.removeClass("greenPopup");

					if (type == "load")
						prompt.addClass("blackPopup");
					else
						prompt.removeClass("blackPopup");
				}
				if (ajaxed)
					prompt.addClass("ajaxed");
				else
					prompt.removeClass("ajaxed");

				prompt.find(".formErrorContent").html(promptText);

				var pos = methods._calculatePosition(field, prompt, options);
				var css = {"top": pos.callerTopPosition,
				"left": pos.callerleftPosition,
				"marginTop": pos.marginTopSize};

				if (noAnimation)
					prompt.css(css);
				else
					prompt.animate(css);
			}
		},
		/**
		* Closes the prompt associated with the given field
		*
		* @param {jqObject}
		*            field
		*/
		 _closePrompt: function(field) {
			 var prompt = methods._getPrompt(field);
			 if (prompt)
				 prompt.fadeTo("fast", 0, function() {
					 prompt.parent('.formErrorOuter').remove();
					 prompt.remove();
				 });
		 },
		 closePrompt: function(field) {
			 return methods._closePrompt(field);
		 },
		/**
		* Returns the error prompt matching the field if any
		*
		* @param {jqObject}
		*            field
		* @return undefined or the error prompt (jqObject)
		*/
		_getPrompt: function(field) {
				var formId = $(field).closest('form, .validationEngineContainer').attr('id');
			var className = methods._getClassName(field.attr("id")) + "formError";
				var match = $("." + methods._escapeExpression(className) + '.parentForm' + methods._getClassName(formId))[0];
			if (match)
			return $(match);
		},
		/**
		  * Returns the escapade classname
		  *
		  * @param {selector}
		  *            className
		  */
		  _escapeExpression: function (selector) {
			  return selector.replace(/([#;&,\.\+\*\~':"\!\^$\[\]\(\)=>\|])/g, "\\$1");
		  },
		/**
		 * returns true if we are in a RTLed document
		 *
		 * @param {jqObject} field
		 */
		isRTL: function(field)
		{
			var $document = $(document);
			var $body = $('body');
			var rtl =
				(field && field.hasClass('rtl')) ||
				(field && (field.attr('dir') || '').toLowerCase()==='rtl') ||
				$document.hasClass('rtl') ||
				($document.attr('dir') || '').toLowerCase()==='rtl' ||
				$body.hasClass('rtl') ||
				($body.attr('dir') || '').toLowerCase()==='rtl';
			return Boolean(rtl);
		},
		/**
		* Calculates prompt position
		*
		* @param {jqObject}
		*            field
		* @param {jqObject}
		*            the prompt
		* @param {Map}
		*            options
		* @return positions
		*/
		_calculatePosition: function (field, promptElmt, options) {

			var promptTopPosition, promptleftPosition, marginTopSize;
			var fieldWidth 	= field.width();
			var fieldLeft 	= field.position().left; 
			var fieldTop 	=  field.position().top;
			var fieldHeight 	=  field.height();	
			var promptHeight = promptElmt.height();


			// is the form contained in an overflown container?
			promptTopPosition = promptleftPosition = 0;
			// compensation for the arrow
			marginTopSize = -promptHeight;
		

			//prompt positioning adjustment support
			//now you can adjust prompt position
			//usage: positionType:Xshift,Yshift
			//for example:
			//   bottomLeft:+20 means bottomLeft position shifted by 20 pixels right horizontally
			//   topRight:20, -15 means topRight position shifted by 20 pixels to right and 15 pixels to top
			//You can use +pixels, - pixels. If no sign is provided than + is default.
			var positionType=field.data("promptPosition") || options.promptPosition;
			var shift1="";
			var shift2="";
			var shiftX=0;
			var shiftY=0;
			if (typeof(positionType)=='string') {
				//do we have any position adjustments ?
				if (positionType.indexOf(":")!=-1) {
					shift1=positionType.substring(positionType.indexOf(":")+1);
					positionType=positionType.substring(0,positionType.indexOf(":"));

					//if any advanced positioning will be needed (percents or something else) - parser should be added here
					//for now we use simple parseInt()

					//do we have second parameter?
					if (shift1.indexOf(",") !=-1) {
						shift2=shift1.substring(shift1.indexOf(",") +1);
						shift1=shift1.substring(0,shift1.indexOf(","));
						shiftY=parseInt(shift2);
						if (isNaN(shiftY)) shiftY=0;
					};

					shiftX=parseInt(shift1);
					if (isNaN(shift1)) shift1=0;

				};
			};

			
			switch (positionType) {
				default:
				case "topRight":
					promptleftPosition +=  fieldLeft + fieldWidth - 30;
					promptTopPosition +=  fieldTop;
					break;

				case "topLeft":
					promptTopPosition +=  fieldTop;
					promptleftPosition += fieldLeft; 
					break;

				case "centerRight":
					promptTopPosition = fieldTop+4;
					marginTopSize = 0;
					promptleftPosition= fieldLeft + field.outerWidth(true)+5;
					break;
				case "centerLeft":
					promptleftPosition = fieldLeft - (promptElmt.width() + 2);
					promptTopPosition = fieldTop+4;
					marginTopSize = 0;
					
					break;

				case "bottomLeft":
					promptTopPosition = fieldTop + field.height() + 5;
					marginTopSize = 0;
					promptleftPosition = fieldLeft;
					break;
				case "bottomRight":
					promptleftPosition = fieldLeft + fieldWidth - 30;
					promptTopPosition =  fieldTop +  field.height() + 5;
					marginTopSize = 0;
					break;
				case "inline":
					promptleftPosition = 0;
					promptTopPosition = 0;
					marginTopSize = 0;
			};

		

			//apply adjusments if any
			promptleftPosition += shiftX;
			promptTopPosition  += shiftY;

			return {
				"callerTopPosition": promptTopPosition + "px",
				"callerleftPosition": promptleftPosition + "px",
				"marginTopSize": marginTopSize + "px"
			};
		},
		/**
		* Saves the user options and variables in the form.data
		*
		* @param {jqObject}
		*            form - the form where the user option should be saved
		* @param {Map}
		*            options - the user options
		* @return the user options (extended from the defaults)
		*/
		 _saveOptions: function(form, options) {

			 // is there a language localisation ?
			 if ($.validationEngineLanguage)
			 var allRules = $.validationEngineLanguage.allRules;
			 else
			 $.error("jQuery.validationEngine rules are not loaded, plz add localization files to the page");
			 // --- Internals DO NOT TOUCH or OVERLOAD ---
			 // validation rules and i18
			 $.validationEngine.defaults.allrules = allRules;

			 var userOptions = $.extend(true,{},$.validationEngine.defaults,options);

			 form.data('jqv', userOptions);
			 return userOptions;
		 },

		 /**
		 * Removes forbidden characters from class name
		 * @param {String} className
		 */
		 _getClassName: function(className) {
			 if(className)
				 return className.replace(/:/g, "_").replace(/\./g, "_");
					  },
		/**
		 * Escape special character for jQuery selector
		 * http://totaldev.com/content/escaping-characters-get-valid-jquery-id
		 * @param {String} selector
		 */
		 _jqSelector: function(str){
			return str.replace(/([;&,\.\+\*\~':"\!\^#$%@\[\]\(\)=>\|])/g, '\\$1');
		},
		/**
		* Conditionally required field
		*
		* @param {jqObject} field
		* @param {Array[String]} rules
		* @param {int} i rules index
		* @param {Map}
		* user options
		* @return an error string if validation failed
		*/
		_condRequired: function(field, rules, i, options) {
			var idx, dependingField;

			for(idx = (i + 1); idx < rules.length; idx++) {
				dependingField = jQuery("#" + rules[idx]).first();

				/* Use _required for determining wether dependingField has a value.
				 * There is logic there for handling all field types, and default value; so we won't replicate that here
				 * Indicate this special use by setting the last parameter to true so we only validate the dependingField on chackboxes and radio buttons (#462)
				 */
				if (dependingField.length && methods._required(dependingField, ["required"], 0, options, true) == undefined) {
					/* We now know any of the depending fields has a value,
					 * so we can validate this field as per normal required code
					 */
					return methods._required(field, ["required"], 0, options);
				}
			}
		},

	    _submitButtonClick: function(event) {
	        var button = $(this);
	        var form = button.closest('form, .validationEngineContainer');
	        form.data("jqv_submitButton", button.attr("id"));
	    }
		  };

	 /**
	 * Plugin entry point.
	 * You may pass an action as a parameter or a list of options.
	 * if none, the init and attach methods are being called.
	 * Remember: if you pass options, the attached method is NOT called automatically
	 *
	 * @param {String}
	 *            method (optional) action
	 */
	 $.fn.validationEngine = function(method) {

		 var form = $(this);
		 if(!form[0]) return form;  // stop here if the form does not exist

		 if (typeof(method) == 'string' && method.charAt(0) != '_' && methods[method]) {

			 // make sure init is called once
			 if(method != "showPrompt" && method != "hide" && method != "hideAll")
			 methods.init.apply(form);

			 return methods[method].apply(form, Array.prototype.slice.call(arguments, 1));
		 } else if (typeof method == 'object' || !method) {

			 // default constructor with or without arguments
			 methods.init.apply(form, arguments);
			 return methods.attach.apply(form);
		 } else {
			 $.error('Method ' + method + ' does not exist in jQuery.validationEngine');
		 }
	};



	// LEAK GLOBAL OPTIONS
	$.validationEngine= {fieldIdCounter: 0,defaults:{

		// Name of the event triggering field validation
		validationEventTrigger: "blur",
		// Automatically scroll viewport to the first error
		scroll: true,
		// Focus on the first input
		focusFirstField:true,
		// Show prompts, set to false to disable prompts
		showPrompts: true,
       // Should we attempt to validate non-visible input fields contained in the form? (Useful in cases of tabbed containers, e.g. jQuery-UI tabs)
       validateNonVisibleFields: false,
		// Opening box position, possible locations are: topLeft,
		// topRight, bottomLeft, centerRight, bottomRight, inline
		// inline gets inserted after the validated field or into an element specified in data-prompt-target
		promptPosition: "topRight",
		bindMethod:"bind",
		// internal, automatically set to true when it parse a _ajax rule
		inlineAjax: false,
		// if set to true, the form data is sent asynchronously via ajax to the form.action url (get)
		ajaxFormValidation: false,
		// The url to send the submit ajax validation (default to action)
		ajaxFormValidationURL: false,
		// HTTP method used for ajax validation
		ajaxFormValidationMethod: 'get',
		// Ajax form validation callback method: boolean onComplete(form, status, errors, options)
		// retuns false if the form.submit event needs to be canceled.
		onAjaxFormComplete: $.noop,
		// called right before the ajax call, may return false to cancel
		onBeforeAjaxFormValidation: $.noop,
		// Stops form from submitting and execute function assiciated with it
		onValidationComplete: false,

		// Used when you have a form fields too close and the errors messages are on top of other disturbing viewing messages
		doNotShowAllErrosOnSubmit: false,
		// Object where you store custom messages to override the default error messages
		custom_error_messages:{},
		// true if you want to vind the input fields
		binded: true,
		// set to true, when the prompt arrow needs to be displayed
		showArrow: true,
		// did one of the validation fail ? kept global to stop further ajax validations
		isError: false,
		// Limit how many displayed errors a field can have
		maxErrorsPerField: false,
		
		// Caches field validation status, typically only bad status are created.
		// the array is used during ajax form validation to detect issues early and prevent an expensive submit
		ajaxValidCache: {},
		// Auto update prompt position after window resize
		autoPositionUpdate: false,

		InvalidFields: [],
		onFieldSuccess: false,
		onFieldFailure: false,
		onSuccess: false,
		onFailure: false,
		validateAttribute: "class",
		addSuccessCssClassToField: "",
		addFailureCssClassToField: "",
		
		// Auto-hide prompt
		autoHidePrompt: false,
		// Delay before auto-hide
		autoHideDelay: 10000,
		// Fade out duration while hiding the validations
		fadeDuration: 0.3,
	 // Use Prettify select library
	 prettySelect: false,
	 // Add css class on prompt
	 addPromptClass : "",
	 // Custom ID uses prefix
	 usePrefix: "",
	 // Custom ID uses suffix
	 useSuffix: "",
	 // Only show one message per error prompt
	 showOneMessage: false
	}};
	$(function(){$.validationEngine.defaults.promptPosition = methods.isRTL()?'topLeft':"topRight"});
})(jQuery);


;
(function($){
    $.fn.validationEngineLanguage = function(){
    };
    $.validationEngineLanguage = {
        newLang: function(){
            $.validationEngineLanguage.allRules = {
                "required": { // Add your regex rules here, you can take telephone as an example
                    "regex": "none",
                    "alertText": "* This field is required",
                    "alertTextCheckboxMultiple": "* Please select an option",
                    "alertTextCheckboxe": "* This checkbox is required",
                    "alertTextDateRange": "* Both date range fields are required"
                },
                "requiredInFunction": { 
                    "func": function(field, rules, i, options){
                        return (field.val() == "test") ? true : false;
                    },
                    "alertText": "* Field must equal test"
                },
                "dateRange": {
                    "regex": "none",
                    "alertText": "* Invalid ",
                    "alertText2": "Date Range"
                },
                "dateTimeRange": {
                    "regex": "none",
                    "alertText": "* Invalid ",
                    "alertText2": "Date Time Range"
                },
                "minSize": {
                    "regex": "none",
                    "alertText": "* Minimum ",
                    "alertText2": " characters required"
                },
                "maxSize": {
                    "regex": "none",
                    "alertText": "* Maximum ",
                    "alertText2": " characters allowed"
                },
				"groupRequired": {
                    "regex": "none",
                    "alertText": "* You must fill one of the following fields"
                },
                "min": {
                    "regex": "none",
                    "alertText": "* Minimum value is "
                },
                "max": {
                    "regex": "none",
                    "alertText": "* Maximum value is "
                },
                "past": {
                    "regex": "none",
                    "alertText": "* Date prior to "
                },
                "future": {
                    "regex": "none",
                    "alertText": "* Date past "
                },	
                "maxCheckbox": {
                    "regex": "none",
                    "alertText": "* Maximum ",
                    "alertText2": " options allowed"
                },
                "minCheckbox": {
                    "regex": "none",
                    "alertText": "* Please select ",
                    "alertText2": " options"
                },
                "equals": {
                    "regex": "none",
                    "alertText": "* Fields do not match"
                },
                "creditCard": {
                    "regex": "none",
                    "alertText": "* Invalid credit card number"
                },
                "phone": {
                    // credit: jquery.h5validate.js / orefalo
                    "regex": /^([\+][0-9]{1,3}[\ \.\-])?([\(]{1}[0-9]{2,6}[\)])?([0-9\ \.\-\/]{3,20})((x|ext|extension)[\ ]?[0-9]{1,4})?$/,
                    "alertText": "* Invalid phone number"
                },
                "email": {
                    // HTML5 compatible email regex ( http://www.whatwg.org/specs/web-apps/current-work/multipage/states-of-the-type-attribute.html#    e-mail-state-%28type=email%29 )
                    "regex": /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/,
                    "alertText": "* Invalid email address"
                },
                "integer": {
                    "regex": /^[\-\+]?\d+$/,
                    "alertText": "* Not a valid integer"
                },
                "number": {
                    // Number, including positive, negative, and floating decimal. credit: orefalo
                    "regex": /^[\-\+]?((([0-9]{1,3})([,][0-9]{3})*)|([0-9]+))?([\.]([0-9]+))?$/,
                    "alertText": "* Invalid floating decimal number"
                },
                "date": {                    
                    //	Check if date is valid by leap year
			"func": function (field) {
					var pattern = new RegExp(/^(\d{4})[\/\-\.](0?[1-9]|1[012])[\/\-\.](0?[1-9]|[12][0-9]|3[01])$/);
					var match = pattern.exec(field.val());
					if (match == null)
					   return false;
	
					var year = match[1];
					var month = match[2]*1;
					var day = match[3]*1;					
					var date = new Date(year, month - 1, day); // because months starts from 0.
	
					return (date.getFullYear() == year && date.getMonth() == (month - 1) && date.getDate() == day);
				},                		
			 "alertText": "* Invalid date, must be in YYYY-MM-DD format"
                },
                "ipv4": {
                    "regex": /^((([01]?[0-9]{1,2})|(2[0-4][0-9])|(25[0-5]))[.]){3}(([0-1]?[0-9]{1,2})|(2[0-4][0-9])|(25[0-5]))$/,
                    "alertText": "* Invalid IP address"
                },
                "url": {
                    "regex": /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i,
                    "alertText": "* Invalid URL"
                },
                "onlyNumberSp": {
                    "regex": /^[0-9\ ]+$/,
                    "alertText": "* Numbers only"
                },
                "onlyLetterSp": {
                    "regex": /^[a-zA-Z\ \']+$/,
                    "alertText": "* Letters only"
                },
                "onlyLetterNumber": {
                    "regex": /^[0-9a-zA-Z]+$/,
                    "alertText": "* No special characters allowed"
                },
                // --- CUSTOM RULES -- Those are specific to the demos, they can be removed or changed to your likings
                "ajaxUserCall": {
                    "url": "ajaxValidateFieldUser",
                    // you may want to pass extra data on the ajax call
                    "extraData": "name=eric",
                    "alertText": "* This user is already taken",
                    "alertTextLoad": "* Validating, please wait"
                },
				"ajaxUserCallPhp": {
                    "url": "phpajax/ajaxValidateFieldUser.php",
                    // you may want to pass extra data on the ajax call
                    "extraData": "name=eric",
                    // if you provide an "alertTextOk", it will show as a green prompt when the field validates
                    "alertTextOk": "* This username is available",
                    "alertText": "* This user is already taken",
                    "alertTextLoad": "* Validating, please wait"
                },
                "ajaxNameCall": {
                    // remote json service location
                    "url": "ajaxValidateFieldName",
                    // error
                    "alertText": "* This name is already taken",
                    // if you provide an "alertTextOk", it will show as a green prompt when the field validates
                    "alertTextOk": "* This name is available",
                    // speaks by itself
                    "alertTextLoad": "* Validating, please wait"
                },
				 "ajaxNameCallPhp": {
	                    // remote json service location
	                    "url": "phpajax/ajaxValidateFieldName.php",
	                    // error
	                    "alertText": "* This name is already taken",
	                    // speaks by itself
	                    "alertTextLoad": "* Validating, please wait"
	                },
                "validate2fields": {
                    "alertText": "* Please input HELLO"
                },
	            //tls warning:homegrown not fielded 
                "dateFormat":{
                    "regex": /^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])$|^(?:(?:(?:0?[13578]|1[02])(\/|-)31)|(?:(?:0?[1,3-9]|1[0-2])(\/|-)(?:29|30)))(\/|-)(?:[1-9]\d\d\d|\d[1-9]\d\d|\d\d[1-9]\d|\d\d\d[1-9])$|^(?:(?:0?[1-9]|1[0-2])(\/|-)(?:0?[1-9]|1\d|2[0-8]))(\/|-)(?:[1-9]\d\d\d|\d[1-9]\d\d|\d\d[1-9]\d|\d\d\d[1-9])$|^(0?2(\/|-)29)(\/|-)(?:(?:0[48]00|[13579][26]00|[2468][048]00)|(?:\d\d)?(?:0[48]|[2468][048]|[13579][26]))$/,
                    "alertText": "* Invalid Date"
                },
                //tls warning:homegrown not fielded 
				"dateTimeFormat": {
	                "regex": /^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])\s+(1[012]|0?[1-9]){1}:(0?[1-5]|[0-6][0-9]){1}:(0?[0-6]|[0-6][0-9]){1}\s+(am|pm|AM|PM){1}$|^(?:(?:(?:0?[13578]|1[02])(\/|-)31)|(?:(?:0?[1,3-9]|1[0-2])(\/|-)(?:29|30)))(\/|-)(?:[1-9]\d\d\d|\d[1-9]\d\d|\d\d[1-9]\d|\d\d\d[1-9])$|^((1[012]|0?[1-9]){1}\/(0?[1-9]|[12][0-9]|3[01]){1}\/\d{2,4}\s+(1[012]|0?[1-9]){1}:(0?[1-5]|[0-6][0-9]){1}:(0?[0-6]|[0-6][0-9]){1}\s+(am|pm|AM|PM){1})$/,
                    "alertText": "* Invalid Date or Date Format",
                    "alertText2": "Expected Format: ",
                    "alertText3": "mm/dd/yyyy hh:mm:ss AM|PM or ", 
                    "alertText4": "yyyy-mm-dd hh:mm:ss AM|PM"
	            }
            };
            
        }
    };

    $.validationEngineLanguage.newLang();
    
})(jQuery);
;
/*!
 * jQuery blockUI plugin
 * Version 2.58.0-2013.04.04
 * @requires jQuery v1.7 or later
 *
 * Examples at: http://malsup.com/jquery/block/
 * Copyright (c) 2007-2013 M. Alsup
 * Dual licensed under the MIT and GPL licenses:
 * http://www.opensource.org/licenses/mit-license.php
 * http://www.gnu.org/licenses/gpl.html
 *
 * Thanks to Amir-Hossein Sobhi for some excellent contributions!
 */

;(function() {
/*jshint eqeqeq:false curly:false latedef:false */
"use strict";

	function setup($) {
		$.fn._fadeIn = $.fn.fadeIn;

		var noOp = $.noop || function() {};

		// this bit is to ensure we don't call setExpression when we shouldn't (with extra muscle to handle
		// retarded userAgent strings on Vista)
		var msie = /MSIE/.test(navigator.userAgent);
		var ie6  = /MSIE 6.0/.test(navigator.userAgent) && ! /MSIE 8.0/.test(navigator.userAgent);
		var mode = document.documentMode || 0;
		var setExpr = $.isFunction( document.createElement('div').style.setExpression );

		// global $ methods for blocking/unblocking the entire page
		$.blockUI   = function(opts) { install(window, opts); };
		$.unblockUI = function(opts) { remove(window, opts); };

		// convenience method for quick growl-like notifications  (http://www.google.com/search?q=growl)
		$.growlUI = function(title, message, timeout, onClose) {
			var $m = $('<div class="growlUI"></div>');
			if (title) $m.append('<h1>'+title+'</h1>');
			if (message) $m.append('<h2>'+message+'</h2>');
			if (timeout === undefined) timeout = 3000;
			$.blockUI({
				message: $m, fadeIn: 700, fadeOut: 1000, centerY: false,
				timeout: timeout, showOverlay: false,
				onUnblock: onClose,
				css: $.blockUI.defaults.growlCSS
			});
		};

		// plugin method for blocking element content
		$.fn.block = function(opts) {
			if ( this[0] === window ) {
				$.blockUI( opts );
				return this;
			}
			var fullOpts = $.extend({}, $.blockUI.defaults, opts || {});
			this.each(function() {
				var $el = $(this);
				if (fullOpts.ignoreIfBlocked && $el.data('blockUI.isBlocked'))
					return;
				$el.unblock({ fadeOut: 0 });
			});

			return this.each(function() {
				if ($.css(this,'position') == 'static') {
					this.style.position = 'relative';
					$(this).data('blockUI.static', true);
				}
				this.style.zoom = 1; // force 'hasLayout' in ie
				install(this, opts);
			});
		};

		// plugin method for unblocking element content
		$.fn.unblock = function(opts) {
			if ( this[0] === window ) {
				$.unblockUI( opts );
				return this;
			}
			return this.each(function() {
				remove(this, opts);
			});
		};

		$.blockUI.version = 2.58; // 2nd generation blocking at no extra cost!

		// override these in your code to change the default behavior and style
		$.blockUI.defaults = {
			// message displayed when blocking (use null for no message)
			message:  '<h1>Please wait...</h1>',

			title: null,		// title string; only used when theme == true
			draggable: true,	// only used when theme == true (requires jquery-ui.js to be loaded)

			theme: false, // set to true to use with jQuery UI themes

			// styles for the message when blocking; if you wish to disable
			// these and use an external stylesheet then do this in your code:
			// $.blockUI.defaults.css = {};
			css: {
				padding:	0,
				margin:		0,
				width:		'30%',
				top:		'40%',
				left:		'35%',
				textAlign:	'center',
				color:		'#000',
				border:		'3px solid #aaa',
				backgroundColor:'#fff',
				cursor:		'wait'
			},

			// minimal style set used when themes are used
			themedCSS: {
				width:	'30%',
				top:	'40%',
				left:	'35%'
			},

			// styles for the overlay
			overlayCSS:  {
				backgroundColor:	'#000',
				opacity:			0.6,
				cursor:				'wait'
			},

			// style to replace wait cursor before unblocking to correct issue
			// of lingering wait cursor
			cursorReset: 'default',

			// styles applied when using $.growlUI
			growlCSS: {
				width:		'350px',
				top:		'10px',
				left:		'',
				right:		'10px',
				border:		'none',
				padding:	'5px',
				opacity:	0.6,
				cursor:		'default',
				color:		'#fff',
				backgroundColor: '#000',
				'-webkit-border-radius':'10px',
				'-moz-border-radius':	'10px',
				'border-radius':		'10px'
			},

			// IE issues: 'about:blank' fails on HTTPS and javascript:false is s-l-o-w
			// (hat tip to Jorge H. N. de Vasconcelos)
			/*jshint scripturl:true */
			iframeSrc: /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank',

			// force usage of iframe in non-IE browsers (handy for blocking applets)
			forceIframe: false,

			// z-index for the blocking overlay
			baseZ: 1000,

			// set these to true to have the message automatically centered
			centerX: true, // <-- only effects element blocking (page block controlled via css above)
			centerY: true,

			// allow body element to be stetched in ie6; this makes blocking look better
			// on "short" pages.  disable if you wish to prevent changes to the body height
			allowBodyStretch: true,

			// enable if you want key and mouse events to be disabled for content that is blocked
			bindEvents: true,

			// be default blockUI will supress tab navigation from leaving blocking content
			// (if bindEvents is true)
			constrainTabKey: true,

			// fadeIn time in millis; set to 0 to disable fadeIn on block
			fadeIn:  200,

			// fadeOut time in millis; set to 0 to disable fadeOut on unblock
			fadeOut:  400,

			// time in millis to wait before auto-unblocking; set to 0 to disable auto-unblock
			timeout: 0,

			// disable if you don't want to show the overlay
			showOverlay: true,

			// if true, focus will be placed in the first available input field when
			// page blocking
			focusInput: true,

			// suppresses the use of overlay styles on FF/Linux (due to performance issues with opacity)
			// no longer needed in 2012
			// applyPlatformOpacityRules: true,

			// callback method invoked when fadeIn has completed and blocking message is visible
			onBlock: null,

			// callback method invoked when unblocking has completed; the callback is
			// passed the element that has been unblocked (which is the window object for page
			// blocks) and the options that were passed to the unblock call:
			//	onUnblock(element, options)
			onUnblock: null,

			// callback method invoked when the overlay area is clicked.
			// setting this will turn the cursor to a pointer, otherwise cursor defined in overlayCss will be used.
			onOverlayClick: null,

			// don't ask; if you really must know: http://groups.google.com/group/jquery-en/browse_thread/thread/36640a8730503595/2f6a79a77a78e493#2f6a79a77a78e493
			quirksmodeOffsetHack: 4,

			// class name of the message block
			blockMsgClass: 'blockMsg',

			// if it is already blocked, then ignore it (don't unblock and reblock)
			ignoreIfBlocked: false
		};

		// private data and functions follow...

		var pageBlock = null;
		var pageBlockEls = [];

		function install(el, opts) {
			var css, themedCSS;
			var full = (el == window);
			var msg = (opts && opts.message !== undefined ? opts.message : undefined);
			opts = $.extend({}, $.blockUI.defaults, opts || {});

			if (opts.ignoreIfBlocked && $(el).data('blockUI.isBlocked'))
				return;

			opts.overlayCSS = $.extend({}, $.blockUI.defaults.overlayCSS, opts.overlayCSS || {});
			css = $.extend({}, $.blockUI.defaults.css, opts.css || {});
			if (opts.onOverlayClick)
				opts.overlayCSS.cursor = 'pointer';

			themedCSS = $.extend({}, $.blockUI.defaults.themedCSS, opts.themedCSS || {});
			msg = msg === undefined ? opts.message : msg;

			// remove the current block (if there is one)
			if (full && pageBlock)
				remove(window, {fadeOut:0});

			// if an existing element is being used as the blocking content then we capture
			// its current place in the DOM (and current display style) so we can restore
			// it when we unblock
			if (msg && typeof msg != 'string' && (msg.parentNode || msg.jquery)) {
				var node = msg.jquery ? msg[0] : msg;
				var data = {};
				$(el).data('blockUI.history', data);
				data.el = node;
				data.parent = node.parentNode;
				data.display = node.style.display;
				data.position = node.style.position;
				if (data.parent)
					data.parent.removeChild(node);
			}

			$(el).data('blockUI.onUnblock', opts.onUnblock);
			var z = opts.baseZ;

			// blockUI uses 3 layers for blocking, for simplicity they are all used on every platform;
			// layer1 is the iframe layer which is used to supress bleed through of underlying content
			// layer2 is the overlay layer which has opacity and a wait cursor (by default)
			// layer3 is the message content that is displayed while blocking
			var lyr1, lyr2, lyr3, s;
			if (msie || opts.forceIframe)
				lyr1 = $('<iframe class="blockUI" style="z-index:'+ (z++) +';display:none;border:none;margin:0;padding:0;position:absolute;width:100%;height:100%;top:0;left:0" src="'+opts.iframeSrc+'"></iframe>');
			else
				lyr1 = $('<div class="blockUI" style="display:none"></div>');

			if (opts.theme)
				lyr2 = $('<div class="blockUI blockOverlay ui-widget-overlay" style="z-index:'+ (z++) +';display:none"></div>');
			else
				lyr2 = $('<div class="blockUI blockOverlay" style="z-index:'+ (z++) +';display:none;border:none;margin:0;padding:0;width:100%;height:100%;top:0;left:0"></div>');

			if (opts.theme && full) {
				s = '<div class="blockUI ' + opts.blockMsgClass + ' blockPage ui-dialog ui-widget ui-corner-all" style="z-index:'+(z+10)+';display:none;position:fixed">';
				if ( opts.title ) {
					s += '<div class="ui-widget-header ui-dialog-titlebar ui-corner-all blockTitle">'+(opts.title || '&nbsp;')+'</div>';
				}
				s += '<div class="ui-widget-content ui-dialog-content"></div>';
				s += '</div>';
			}
			else if (opts.theme) {
				s = '<div class="blockUI ' + opts.blockMsgClass + ' blockElement ui-dialog ui-widget ui-corner-all" style="z-index:'+(z+10)+';display:none;position:absolute">';
				if ( opts.title ) {
					s += '<div class="ui-widget-header ui-dialog-titlebar ui-corner-all blockTitle">'+(opts.title || '&nbsp;')+'</div>';
				}  
				s += '<div class="ui-widget-content ui-dialog-content"></div>';
				s += '</div>';
			}
			else if (full) {
				s = '<div class="blockUI ' + opts.blockMsgClass + ' blockPage" style="z-index:'+(z+10)+';display:none;position:fixed"></div>';
			}
			else {
				s = '<div class="blockUI ' + opts.blockMsgClass + ' blockElement" style="z-index:'+(z+10)+';display:none;position:absolute"></div>';
			}
			lyr3 = $(s);

			// if we have a message, style it
			if (msg) {
				if (opts.theme) {
					lyr3.css(themedCSS);
					lyr3.addClass('ui-widget-content');
				}
				else
					lyr3.css(css);
			}

			// style the overlay
			if (!opts.theme /*&& (!opts.applyPlatformOpacityRules)*/)
				lyr2.css(opts.overlayCSS);
			lyr2.css('position', full ? 'fixed' : 'absolute');

			// make iframe layer transparent in IE
			if (msie || opts.forceIframe)
				lyr1.css('opacity',0.0);

			//$([lyr1[0],lyr2[0],lyr3[0]]).appendTo(full ? 'body' : el);
			var layers = [lyr1,lyr2,lyr3], $par = full ? $('body') : $(el);
			$.each(layers, function() {
				this.appendTo($par);
			});

			if (opts.theme && opts.draggable && $.fn.draggable) {
				lyr3.draggable({
					handle: '.ui-dialog-titlebar',
					cancel: 'li'
				});
			}

			// ie7 must use absolute positioning in quirks mode and to account for activex issues (when scrolling)
			var expr = setExpr && (!$.support.boxModel || $('object,embed', full ? null : el).length > 0);
			if (ie6 || expr) {
				// give body 100% height
				if (full && opts.allowBodyStretch && $.support.boxModel)
					$('html,body').css('height','100%');

				// fix ie6 issue when blocked element has a border width
				if ((ie6 || !$.support.boxModel) && !full) {
					var t = sz(el,'borderTopWidth'), l = sz(el,'borderLeftWidth');
					var fixT = t ? '(0 - '+t+')' : 0;
					var fixL = l ? '(0 - '+l+')' : 0;
				}

				// simulate fixed position
				$.each(layers, function(i,o) {
					var s = o[0].style;
					s.position = 'absolute';
					if (i < 2) {
						if (full)
							s.setExpression('height','Math.max(document.body.scrollHeight, document.body.offsetHeight) - (jQuery.support.boxModel?0:'+opts.quirksmodeOffsetHack+') + "px"');
						else
							s.setExpression('height','this.parentNode.offsetHeight + "px"');
						if (full)
							s.setExpression('width','jQuery.support.boxModel && document.documentElement.clientWidth || document.body.clientWidth + "px"');
						else
							s.setExpression('width','this.parentNode.offsetWidth + "px"');
						if (fixL) s.setExpression('left', fixL);
						if (fixT) s.setExpression('top', fixT);
					}
					else if (opts.centerY) {
						if (full) s.setExpression('top','(document.documentElement.clientHeight || document.body.clientHeight) / 2 - (this.offsetHeight / 2) + (blah = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + "px"');
						s.marginTop = 0;
					}
					else if (!opts.centerY && full) {
						var top = (opts.css && opts.css.top) ? parseInt(opts.css.top, 10) : 0;
						var expression = '((document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + '+top+') + "px"';
						s.setExpression('top',expression);
					}
				});
			}

			// show the message
			if (msg) {
				if (opts.theme)
					lyr3.find('.ui-widget-content').append(msg);
				else
					lyr3.append(msg);
				if (msg.jquery || msg.nodeType)
					$(msg).show();
			}

			if ((msie || opts.forceIframe) && opts.showOverlay)
				lyr1.show(); // opacity is zero
			if (opts.fadeIn) {
				var cb = opts.onBlock ? opts.onBlock : noOp;
				var cb1 = (opts.showOverlay && !msg) ? cb : noOp;
				var cb2 = msg ? cb : noOp;
				if (opts.showOverlay)
					lyr2._fadeIn(opts.fadeIn, cb1);
				if (msg)
					lyr3._fadeIn(opts.fadeIn, cb2);
			}
			else {
				if (opts.showOverlay)
					lyr2.show();
				if (msg)
					lyr3.show();
				if (opts.onBlock)
					opts.onBlock();
			}

			// bind key and mouse events
			bind(1, el, opts);

			if (full) {
				pageBlock = lyr3[0];
				pageBlockEls = $(':input:enabled:visible',pageBlock);
				if (opts.focusInput)
					setTimeout(focus, 20);
			}
			else
				center(lyr3[0], opts.centerX, opts.centerY);

			if (opts.timeout) {
				// auto-unblock
				var to = setTimeout(function() {
					if (full)
						$.unblockUI(opts);
					else
						$(el).unblock(opts);
				}, opts.timeout);
				$(el).data('blockUI.timeout', to);
			}
		}

		// remove the block
		function remove(el, opts) {
			var count;
			var full = (el == window);
			var $el = $(el);
			var data = $el.data('blockUI.history');
			var to = $el.data('blockUI.timeout');
			if (to) {
				clearTimeout(to);
				$el.removeData('blockUI.timeout');
			}
			opts = $.extend({}, $.blockUI.defaults, opts || {});
			bind(0, el, opts); // unbind events

			if (opts.onUnblock === null) {
				opts.onUnblock = $el.data('blockUI.onUnblock');
				$el.removeData('blockUI.onUnblock');
			}

			var els;
			if (full) // crazy selector to handle odd field errors in ie6/7
				els = $('body').children().filter('.blockUI').add('body > .blockUI');
			else
				els = $el.find('>.blockUI');

			// fix cursor issue
			if ( opts.cursorReset ) {
				if ( els.length > 1 )
					els[1].style.cursor = opts.cursorReset;
				if ( els.length > 2 )
					els[2].style.cursor = opts.cursorReset;
			}

			if (full)
				pageBlock = pageBlockEls = null;

			if (opts.fadeOut) {
				count = els.length;
				els.fadeOut(opts.fadeOut, function() { 
					if ( --count === 0)
						reset(els,data,opts,el);
				});
			}
			else
				reset(els, data, opts, el);
		}

		// move blocking element back into the DOM where it started
		function reset(els,data,opts,el) {
			var $el = $(el);
			els.each(function(i,o) {
				// remove via DOM calls so we don't lose event handlers
				if (this.parentNode)
					this.parentNode.removeChild(this);
			});

			if (data && data.el) {
				data.el.style.display = data.display;
				data.el.style.position = data.position;
				if (data.parent)
					data.parent.appendChild(data.el);
				$el.removeData('blockUI.history');
			}

			if ($el.data('blockUI.static')) {
				$el.css('position', 'static'); // #22
			}

			if (typeof opts.onUnblock == 'function')
				opts.onUnblock(el,opts);

			// fix issue in Safari 6 where block artifacts remain until reflow
			var body = $(document.body), w = body.width(), cssW = body[0].style.width;
			body.width(w-1).width(w);
			body[0].style.width = cssW;
		}

		// bind/unbind the handler
		function bind(b, el, opts) {
			var full = el == window, $el = $(el);

			// don't bother unbinding if there is nothing to unbind
			if (!b && (full && !pageBlock || !full && !$el.data('blockUI.isBlocked')))
				return;

			$el.data('blockUI.isBlocked', b);

			// don't bind events when overlay is not in use or if bindEvents is false
			if (!opts.bindEvents || (b && !opts.showOverlay))
				return;

			// bind anchors and inputs for mouse and key events
			var events = 'mousedown mouseup keydown keypress keyup touchstart touchend touchmove';
			if (b)
				$(document).bind(events, opts, handler);
			else
				$(document).unbind(events, handler);

		// former impl...
		//		var $e = $('a,:input');
		//		b ? $e.bind(events, opts, handler) : $e.unbind(events, handler);
		}

		// event handler to suppress keyboard/mouse events when blocking
		function handler(e) {
			// allow tab navigation (conditionally)
			if (e.keyCode && e.keyCode == 9) {
				if (pageBlock && e.data.constrainTabKey) {
					var els = pageBlockEls;
					var fwd = !e.shiftKey && e.target === els[els.length-1];
					var back = e.shiftKey && e.target === els[0];
					if (fwd || back) {
						setTimeout(function(){focus(back);},10);
						return false;
					}
				}
			}
			var opts = e.data;
			var target = $(e.target);
			if (target.hasClass('blockOverlay') && opts.onOverlayClick)
				opts.onOverlayClick();

			// allow events within the message content
			if (target.parents('div.' + opts.blockMsgClass).length > 0)
				return true;

			// allow events for content that is not being blocked
			return target.parents().children().filter('div.blockUI').length === 0;
		}

		function focus(back) {
			if (!pageBlockEls)
				return;
			var e = pageBlockEls[back===true ? pageBlockEls.length-1 : 0];
			if (e)
				e.focus();
		}

		function center(el, x, y) {
			var p = el.parentNode, s = el.style;
			var l = ((p.offsetWidth - el.offsetWidth)/2) - sz(p,'borderLeftWidth');
			var t = ((p.offsetHeight - el.offsetHeight)/2) - sz(p,'borderTopWidth');
			if (x) s.left = l > 0 ? (l+'px') : '0';
			if (y) s.top  = t > 0 ? (t+'px') : '0';
		}

		function sz(el, p) {
			return parseInt($.css(el,p),10)||0;
		}

	}


	/*global define:true */
	if (typeof define === 'function' && define.amd && define.amd.jQuery) {
		define(['jquery'], setup);
	} else {
		setup(jQuery);
	}

})();
;
/**
 * State-based routing for AngularJS 1.x
 * NOTICE: This monolithic bundle also bundles the @uirouter/core code.
 *         This causes it to be incompatible with plugins that depend on @uirouter/core.
 *         We recommend switching to the ui-router-core.js and ui-router-angularjs.js bundles instead.
 *         For more information, see https://ui-router.github.io/blog/uirouter-for-angularjs-umd-bundles
 * @version v1.0.24
 * @link https://ui-router.github.io
 * @license MIT License, http://www.opensource.org/licenses/MIT
 */
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports,require("angular")):"function"==typeof define&&define.amd?define(["exports","angular"],e):e((t=t||self)["@uirouter/angularjs"]={},t.angular)}(this,function(d,t){"use strict";var e=angular,$=t&&t.module?t:e,n=function(){for(var t=0,e=0,r=arguments.length;e<r;e++)t+=arguments[e].length;var n=Array(t),i=0;for(e=0;e<r;e++)for(var o=arguments[e],a=0,u=o.length;a<u;a++,i++)n[i]=o[a];return n};function s(r){return function t(){if(arguments.length>=r.length)return r.apply(this,arguments);var e=Array.prototype.slice.call(arguments);return t.bind.apply(t,n([this],e))}}function r(){var r=arguments,n=r.length-1;return function(){for(var t=n,e=r[n].apply(this,arguments);t--;)e=r[t].call(this,e);return e}}function c(){for(var t=[],e=0;e<arguments.length;e++)t[e]=arguments[e];return r.apply(null,[].slice.call(arguments).reverse())}var m=function(e){return function(t){return t&&t[e]}},y=s(function(t,e,r){return r&&r[t]===e}),R=function(t){return c.apply(null,t.split(".").map(m))},l=function(r){return function(){for(var t=[],e=0;e<arguments.length;e++)t[e]=arguments[e];return!r.apply(null,t)}};function i(r,n){return function(){for(var t=[],e=0;e<arguments.length;e++)t[e]=arguments[e];return r.apply(null,t)&&n.apply(null,t)}}function o(r,n){return function(){for(var t=[],e=0;e<arguments.length;e++)t[e]=arguments[e];return r.apply(null,t)||n.apply(null,t)}}function a(e){return function(t){return e===t}}var u=function(r){return function(t){return t.reduce(function(t,e){return t&&!!r(e)},!0)}},f=function(r){return function(t){return t.reduce(function(t,e){return t||!!r(e)},!1)}},h=function(e){return function(t){return null!=t&&t.constructor===e||t instanceof e}},p=function(t){return function(){return t}};function v(e,r){return function(t){return t[e].apply(t,r)}}function g(r){return function(t){for(var e=0;e<r.length;e++)if(r[e][0](t))return r[e][1](t)}}function w(e){return function(t){return typeof t===e}}function _(t){return null===t}var S=Object.prototype.toString,b=w("undefined"),E=l(b),C=o(_,b),T=w("function"),P=w("number"),k=w("string"),O=function(t){return null!==t&&"object"==typeof t},x=Array.isArray,j=function(t){return"[object Date]"===S.call(t)},V=function(t){return"[object RegExp]"===S.call(t)};function H(t){if(x(t)&&t.length){var e=t.slice(0,-1),r=t.slice(-1);return!(e.filter(l(k)).length||r.filter(l(T)).length)}return T(t)}function I(r,t){return t.reduce(function(t,e){return t[e]=function(t){return function(){throw new Error("No implementation for "+t+". The framework specific code did not implement this method.")}}(r+"."+e+"()"),t},{})}var A=i(O,c(m("then"),T)),D={$q:void 0,$injector:void 0},q=function(){for(var t=0,e=0,r=arguments.length;e<r;e++)t+=arguments[e].length;var n=Array(t),i=0;for(e=0;e<r;e++)for(var o=arguments[e],a=0,u=o.length;a<u;a++,i++)n[i]=o[a];return n},U="object"==typeof self&&self.self===self&&self||"object"==typeof global&&global.global===global&&global||void 0,F=U.angular||{},N=F.fromJson||JSON.parse.bind(JSON),L=F.toJson||JSON.stringify.bind(JSON),M=F.forEach||function(e,r,t){if(x(e))return e.forEach(r,t);Object.keys(e).forEach(function(t){return r(e[t],t)})},B=Object.assign||Ot,G=F.equals||xt;function z(t){return t}function W(){}function J(e,r,n,t,i){void 0===i&&(i=!1);function o(t){return e()[t].bind(n())}return(t=t||Object.keys(e())).reduce(function(t,e){return t[e]=i?function(t){return function(){return r[t]=o(t),r[t].apply(null,arguments)}}(e):o(e),t},r)}var Q=function(t,e){return B(Object.create(t),e)},K=s(Y);function Y(t,e){return-1!==t.indexOf(e)}var Z=s(X);function X(t,e){var r=t.indexOf(e);return 0<=r&&t.splice(r,1),t}var tt=s(et);function et(t,e){return t.push(e),e}function rt(e){return e.slice().forEach(function(t){"function"==typeof t&&t(),Z(e,t)})}function nt(t){for(var e=[],r=1;r<arguments.length;r++)e[r-1]=arguments[r];var n=B.apply(void 0,q([{}],e.reverse()));return B(n,at(t||{},Object.keys(n)))}function it(t,e){return B(t,e)}function ot(t,e){var r=[];for(var n in t.path){if(t.path[n]!==e.path[n])break;r.push(t.path[n])}return r}function at(t,e){var r={};for(var n in t)-1!==e.indexOf(n)&&(r[n]=t[n]);return r}function ut(r,t){return Object.keys(r).filter(l(K(t))).reduce(function(t,e){return t[e]=r[e],t},{})}function st(t,e){return ht(t,m(e))}function ct(t,r){var e=x(t),n=e?[]:{},i=e?function(t){return n.push(t)}:function(t,e){return n[e]=t};return M(t,function(t,e){r(t,e)&&i(t,e)}),n}function ft(t,r){var n;return M(t,function(t,e){n||r(t,e)&&(n=t)}),n}var lt=ht;function ht(t,r,n){return n=n||(x(t)?[]:{}),M(t,function(t,e){return n[e]=r(t,e)}),n}function pt(e){return Object.keys(e).map(function(t){return e[t]})}function vt(t,e){return t&&e}function dt(t,e){return t||e}var mt=function(t,e){return t.concat(e)},yt=function(t,e){return x(e)?t.concat(e.reduce(yt,[])):gt(t,e)};function gt(t,e){return t.push(e),t}function wt(t,e){return K(t,e)?t:gt(t,e)}function _t(t){return t.reduce(mt,[])}function St(t){return t.reduce(yt,[])}var bt=Rt,$t=Rt;function Rt(r,n){return void 0===n&&(n="assert failure"),function(t){var e=r(t);if(!e)throw new Error(T(n)?n(t):n);return e}}function Et(e){return Object.keys(e).map(function(t){return[t,e[t]]})}function Ct(){for(var t=[],e=0;e<arguments.length;e++)t[e]=arguments[e];if(0===t.length)return[];for(var r=t.reduce(function(t,e){return Math.min(e.length,t)},9007199254740991),n=[],i=function(e){switch(t.length){case 1:n.push([t[0][e]]);break;case 2:n.push([t[0][e],t[1][e]]);break;case 3:n.push([t[0][e],t[1][e],t[2][e]]);break;case 4:n.push([t[0][e],t[1][e],t[2][e],t[3][e]]);break;default:n.push(t.map(function(t){return t[e]}))}},o=0;o<r;o++)i(o);return n}function Tt(t,e){var r,n;if(x(e)&&(r=e[0],n=e[1]),!k(r))throw new Error("invalid parameters to applyPairs");return t[r]=n,t}function Pt(t){return t.length&&t[t.length-1]||void 0}function kt(t,e){return e&&Object.keys(e).forEach(function(t){return delete e[t]}),B(e=e||{},t)}function Ot(t){for(var e=1;e<arguments.length;e++){var r=arguments[e];if(r)for(var n=Object.keys(r),i=0;i<n.length;i++)t[n[i]]=r[n[i]]}return t}function xt(t,e){if(t===e)return!0;if(null===t||null===e)return!1;if(t!=t&&e!=e)return!0;var r=typeof t;if(r!=typeof e||"object"!=r)return!1;var n=[t,e];if(u(x)(n))return function(t,e){return t.length===e.length&&Ct(t,e).reduce(function(t,e){return t&&xt(e[0],e[1])},!0)}(t,e);if(u(j)(n))return t.getTime()===e.getTime();if(u(V)(n))return t.toString()===e.toString();if(u(T)(n))return!0;if([T,x,j,V].map(f).reduce(function(t,e){return t||!!e(n)},!1))return!1;var i={};for(var o in t){if(!xt(t[o],e[o]))return!1;i[o]=!0}for(var o in e)if(!i[o])return!1;return!0}function jt(t){return t.catch(function(t){return 0})&&t}function Vt(t){return jt(D.$q.reject(t))}var Ht=(It.is=function(t){return!!/[!,*]+/.exec(t)},It.fromString=function(t){return It.is(t)?new It(t):null},It.prototype.matches=function(t){return this.regexp.test("."+t)},It);function It(t){this.text=t,this.glob=t.split(".");var e=this.text.split(".").map(function(t){return"**"===t?"(?:|(?:\\.[^.]*)*)":"*"===t?"\\.[^.]*":"\\."+t}).join("");this.regexp=new RegExp("^"+e+"$")}var At,Dt=(qt.prototype.enqueue=function(t){var e=this._items;return e.push(t),this._limit&&e.length>this._limit&&this.evict(),t},qt.prototype.evict=function(){var e=this._items.shift();return this._evictListeners.forEach(function(t){return t(e)}),e},qt.prototype.dequeue=function(){if(this.size())return this._items.splice(0,1)[0]},qt.prototype.clear=function(){var t=this._items;return this._items=[],t},qt.prototype.size=function(){return this._items.length},qt.prototype.remove=function(t){var e=this._items.indexOf(t);return-1<e&&this._items.splice(e,1)[0]},qt.prototype.peekTail=function(){return this._items[this._items.length-1]},qt.prototype.peekHead=function(){if(this.size())return this._items[0]},qt);function qt(t,e){void 0===t&&(t=[]),void 0===e&&(e=null),this._items=t,this._limit=e,this._evictListeners=[],this.onEvict=tt(this._evictListeners)}(At=d.RejectType||(d.RejectType={}))[At.SUPERSEDED=2]="SUPERSEDED",At[At.ABORTED=3]="ABORTED",At[At.INVALID=4]="INVALID",At[At.IGNORED=5]="IGNORED",At[At.ERROR=6]="ERROR";var Ut=0,Ft=(Nt.isRejectionPromise=function(t){return t&&"function"==typeof t.then&&h(Nt)(t._transitionRejection)},Nt.superseded=function(t,e){var r=new Nt(d.RejectType.SUPERSEDED,"The transition has been superseded by a different transition",t);return e&&e.redirected&&(r.redirected=!0),r},Nt.redirected=function(t){return Nt.superseded(t,{redirected:!0})},Nt.invalid=function(t){return new Nt(d.RejectType.INVALID,"This transition is invalid",t)},Nt.ignored=function(t){return new Nt(d.RejectType.IGNORED,"The transition was ignored",t)},Nt.aborted=function(t){return new Nt(d.RejectType.ABORTED,"The transition has been aborted",t)},Nt.errored=function(t){return new Nt(d.RejectType.ERROR,"The transition errored",t)},Nt.normalize=function(t){return h(Nt)(t)?t:Nt.errored(t)},Nt.prototype.toString=function(){var t,e=(t=this.detail)&&t.toString!==Object.prototype.toString?t.toString():Qt(t);return"Transition Rejection($id: "+this.$id+" type: "+this.type+", message: "+this.message+", detail: "+e+")"},Nt.prototype.toPromise=function(){return B(Vt(this),{_transitionRejection:this})},Nt);function Nt(t,e,r){this.$id=Ut++,this.type=t,this.message=e,this.detail=r}function Lt(t,e){return e.length<=t?e:e.substr(0,t-3)+"..."}function Mt(t,e){for(;e.length<t;)e+=" ";return e}function Bt(t){return t.replace(/^([A-Z])/,function(t){return t.toLowerCase()}).replace(/([A-Z])/g,function(t){return"-"+t.toLowerCase()})}function Gt(t){var e=zt(t),r=e.match(/^(function [^ ]+\([^)]*\))/),n=r?r[1]:e,i=t.name||"";return i&&n.match(/function \(/)?"function "+i+n.substr(9):n}function zt(t){var e=x(t)?t.slice(-1)[0]:t;return e&&e.toString()||"undefined"}var Wt=Ft.isRejectionPromise,Jt=g([[b,p("undefined")],[_,p("null")],[A,p("[Promise]")],[Wt,function(t){return t._transitionRejection.toString()}],[function(t){return O(t)&&!x(t)&&t.constructor!==Object&&T(t.toString)},function(t){return t.toString()}],[H,Gt],[p(!0),z]]);function Qt(t){var e=[];function r(t){if(O(t)){if(-1!==e.indexOf(t))return"[circular ref]";e.push(t)}return Jt(t)}return b(t)?r(t):JSON.stringify(t,function(t,e){return r(e)}).replace(/\\"/g,'"')}function Kt(r){return function(t){if(!t)return["",""];var e=t.indexOf(r);return-1===e?[t,""]:[t.substr(0,e),t.substr(e+1)]}}function Yt(t){return t.replace(/\/[^/]*$/,"")}function Zt(t){return t?t.replace(/^#/,""):""}var Xt=new RegExp("^(?:[a-z]+:)?//[^/]+/"),te=Kt("#"),ee=Kt("?"),re=Kt("=");function ne(t){var e=new RegExp("("+t+")","g");return function(t){return t.split(e).filter(z)}}function ie(t,e){return k(Pt(t))&&k(e)?t.slice(0,-1).concat(Pt(t)+e):gt(t,e)}var oe={log:W,error:W,table:W};var ae,ue,se,ce=document&&document.documentMode&&9===document.documentMode?window&&window.console?(se=window.console,{log:fe(se.log),error:fe(se.log),table:fe(se.log)}):oe:console.table&&console.error?console:(ae=console,{log:ue=ae.log.bind(ae),error:ae.error?ae.error.bind(ae):ue,table:ae.table?ae.table.bind(ae):ue});function fe(t){return Function.prototype.bind.call(t,se)}function le(t){if(!t)return"ui-view (defunct)";var e=t.creationContext?t.creationContext.name||"(root)":"(none)";return"[ui-view#"+t.id+" "+t.$type+":"+t.fqn+" ("+t.name+"@"+e+")]"}var he;function pe(t){return P(t)?d.Category[t]:d.Category[d.Category[t]]}(he=d.Category||(d.Category={}))[he.RESOLVE=0]="RESOLVE",he[he.TRANSITION=1]="TRANSITION",he[he.HOOK=2]="HOOK",he[he.UIVIEW=3]="UIVIEW",he[he.VIEWCONFIG=4]="VIEWCONFIG";function ve(t){return"Transition #"+de(t)+"-"+me(t)}var de=R("$id"),me=R("router.$id"),ye=(ge.prototype._set=function(e,t){var r=this;t.length||(t=Object.keys(d.Category).map(function(t){return parseInt(t,10)}).filter(function(t){return!isNaN(t)}).map(function(t){return d.Category[t]})),t.map(pe).forEach(function(t){return r._enabled[t]=e})},ge.prototype.enable=function(){for(var t=[],e=0;e<arguments.length;e++)t[e]=arguments[e];this._set(!0,t)},ge.prototype.disable=function(){for(var t=[],e=0;e<arguments.length;e++)t[e]=arguments[e];this._set(!1,t)},ge.prototype.enabled=function(t){return!!this._enabled[pe(t)]},ge.prototype.traceTransitionStart=function(t){this.enabled(d.Category.TRANSITION)&&ce.log(ve(t)+": Started  -> "+Qt(t))},ge.prototype.traceTransitionIgnored=function(t){this.enabled(d.Category.TRANSITION)&&ce.log(ve(t)+": Ignored  <> "+Qt(t))},ge.prototype.traceHookInvocation=function(t,e,r){if(this.enabled(d.Category.HOOK)){var n=R("traceData.hookType")(r)||"internal",i=R("traceData.context.state.name")(r)||R("traceData.context")(r)||"unknown",o=Gt(t.registeredHook.callback);ce.log(ve(e)+":   Hook -> "+n+" context: "+i+", "+Lt(200,o))}},ge.prototype.traceHookResult=function(t,e,r){this.enabled(d.Category.HOOK)&&ce.log(ve(e)+":   <- Hook returned: "+Lt(200,Qt(t)))},ge.prototype.traceResolvePath=function(t,e,r){this.enabled(d.Category.RESOLVE)&&ce.log(ve(r)+":         Resolving "+t+" ("+e+")")},ge.prototype.traceResolvableResolved=function(t,e){this.enabled(d.Category.RESOLVE)&&ce.log(ve(e)+":               <- Resolved  "+t+" to: "+Lt(200,Qt(t.data)))},ge.prototype.traceError=function(t,e){this.enabled(d.Category.TRANSITION)&&ce.log(ve(e)+": <- Rejected "+Qt(e)+", reason: "+t)},ge.prototype.traceSuccess=function(t,e){this.enabled(d.Category.TRANSITION)&&ce.log(ve(e)+": <- Success  "+Qt(e)+", final state: "+t.name)},ge.prototype.traceUIViewEvent=function(t,e,r){void 0===r&&(r=""),this.enabled(d.Category.UIVIEW)&&ce.log("ui-view: "+Mt(30,t)+" "+le(e)+r)},ge.prototype.traceUIViewConfigUpdated=function(t,e){this.enabled(d.Category.UIVIEW)&&this.traceUIViewEvent("Updating",t," with ViewConfig from context='"+e+"'")},ge.prototype.traceUIViewFill=function(t,e){this.enabled(d.Category.UIVIEW)&&this.traceUIViewEvent("Fill",t," with: "+Lt(200,e))},ge.prototype.traceViewSync=function(t){if(this.enabled(d.Category.VIEWCONFIG)){var a="uiview component fqn",e=t.map(function(t){var e,r=t.uiView,n=t.viewConfig,i=r&&r.fqn,o=n&&n.viewDecl.$context.name+": ("+n.viewDecl.$name+")";return(e={})[a]=i,e["view config state (view name)"]=o,e}).sort(function(t,e){return(t[a]||"").localeCompare(e[a]||"")});ce.table(e)}},ge.prototype.traceViewServiceEvent=function(t,e){this.enabled(d.Category.VIEWCONFIG)&&ce.log("VIEWCONFIG: "+t+" "+function(t){var e=t.viewDecl,r=e.$context.name||"(root)";return"[View#"+t.$id+" from '"+r+"' state]: target ui-view: '"+e.$uiViewName+"@"+e.$uiViewContextAnchor+"'"}(e))},ge.prototype.traceViewServiceUIViewEvent=function(t,e){this.enabled(d.Category.VIEWCONFIG)&&ce.log("VIEWCONFIG: "+t+" "+le(e))},ge);function ge(){this._enabled={},this.approximateDigests=0}var we=new ye,_e=(Se.prototype.is=function(t,e){return!0},Se.prototype.encode=function(t,e){return t},Se.prototype.decode=function(t,e){return t},Se.prototype.equals=function(t,e){return t==e},Se.prototype.$subPattern=function(){var t=this.pattern.toString();return t.substr(1,t.length-2)},Se.prototype.toString=function(){return"{ParamType:"+this.name+"}"},Se.prototype.$normalize=function(t){return this.is(t)?t:this.decode(t)},Se.prototype.$asArray=function(t,e){if(!t)return this;if("auto"===t&&!e)throw new Error("'auto' array mode is for query parameters only");return new be(this,t)},Se);function Se(t){this.pattern=/.*/,this.inherit=!0,B(this,t)}function be(n,i){var o=this;function a(t){return x(t)?t:E(t)?[t]:[]}function u(r,n){return function(t){if(x(t)&&0===t.length)return t;var e=ht(a(t),r);return!0===n?0===ct(e,function(t){return!t}).length:function(t){switch(t.length){case 0:return;case 1:return"auto"===i?t[0]:t;default:return t}}(e)}}function s(o){return function(t,e){var r=a(t),n=a(e);if(r.length!==n.length)return!1;for(var i=0;i<r.length;i++)if(!o(r[i],n[i]))return!1;return!0}}["encode","decode","equals","$normalize"].forEach(function(t){var e=n[t].bind(n),r="equals"===t?s:u;o[t]=r(e)}),B(this,{dynamic:n.dynamic,name:n.name,pattern:n.pattern,inherit:n.inherit,raw:n.raw,is:u(n.is.bind(n),!0),$arrayMode:i})}var $e,Re=Object.prototype.hasOwnProperty,Ee=function(t){return 0===["value","type","squash","array","dynamic"].filter(Re.bind(t||{})).length};function Ce(t,e,r){var n=!1===r.reloadOnSearch&&e===d.DefType.SEARCH||void 0,i=ft([r.dynamic,n],E),o=E(i)?{dynamic:i}:{},a=function(t){function e(){return t.value}t=Ee(t)?{value:t}:t,e.__cacheable=!0;var r=H(t.value)?t.value:e;return B(t,{$$fn:r})}(r&&r.params&&r.params[t]);return B(o,a)}($e=d.DefType||(d.DefType={}))[$e.PATH=0]="PATH",$e[$e.SEARCH=1]="SEARCH",$e[$e.CONFIG=2]="CONFIG";var Te=(Pe.values=function(t,e){void 0===e&&(e={});for(var r={},n=0,i=t;n<i.length;n++){var o=i[n];r[o.id]=o.value(e[o.id])}return r},Pe.changed=function(t,e,r){return void 0===e&&(e={}),void 0===r&&(r={}),t.filter(function(t){return!t.type.equals(e[t.id],r[t.id])})},Pe.equals=function(t,e,r){return void 0===e&&(e={}),void 0===r&&(r={}),0===Pe.changed(t,e,r).length},Pe.validates=function(t,e){return void 0===e&&(e={}),t.map(function(t){return t.validates(e[t.id])}).reduce(vt,!0)},Pe.prototype.isDefaultValue=function(t){return this.isOptional&&this.type.equals(this.value(),t)},Pe.prototype.value=function(t){var i=this;return t=function(t){for(var e=0,r=i.replace;e<r.length;e++){var n=r[e];if(n.from===t)return n.to}return t}(t),b(t)?function(){if(i._defaultValueCache)return i._defaultValueCache.defaultValue;if(!D.$injector)throw new Error("Injectable functions cannot be called at configuration time");var t=D.$injector.invoke(i.config.$$fn);if(null!=t&&!i.type.is(t))throw new Error("Default value ("+t+") for parameter '"+i.id+"' is not an instance of ParamType ("+i.type.name+")");return i.config.$$fn.__cacheable&&(i._defaultValueCache={defaultValue:t}),t}():this.type.$normalize(t)},Pe.prototype.isSearch=function(){return this.location===d.DefType.SEARCH},Pe.prototype.validates=function(t){if((b(t)||null===t)&&this.isOptional)return!0;var e=this.type.$normalize(t);if(!this.type.is(e))return!1;var r=this.type.encode(e);return!(k(r)&&!this.type.pattern.exec(r))},Pe.prototype.toString=function(){return"{Param:"+this.id+" "+this.type+" squash: '"+this.squash+"' optional: "+this.isOptional+"}"},Pe);function Pe(t,e,r,n,i){var o=Ce(t,r,i);e=function(t,e,r,n,i){if(t.type&&e&&"string"!==e.name)throw new Error("Param '"+n+"' has two type configurations.");if(t.type&&e&&"string"===e.name&&i.type(t.type))return i.type(t.type);if(e)return e;if(t.type)return t.type instanceof _e?t.type:i.type(t.type);var o=r===d.DefType.CONFIG?"any":r===d.DefType.PATH?"path":r===d.DefType.SEARCH?"query":"string";return i.type(o)}(o,e,r,t,n.paramTypes);var a,u,s=(a={array:r===d.DefType.SEARCH&&"auto"},u=t.match(/\[\]$/)?{array:!0}:{},B(a,u,o).array);e=s?e.$asArray(s,r===d.DefType.SEARCH):e;var c=void 0!==o.value||r===d.DefType.SEARCH,f=E(o.dynamic)?!!o.dynamic:!!e.dynamic,l=E(o.raw)?!!o.raw:!!e.raw,h=function(t,e,r){var n=t.squash;if(!e||!1===n)return!1;if(!E(n)||null==n)return r;if(!0===n||k(n))return n;throw new Error("Invalid squash policy: '"+n+"'. Valid policies: false, true, or arbitrary string")}(o,c,n.defaultSquashPolicy()),p=function(t,e,r,n){var i=[{from:"",to:r||e?void 0:""},{from:null,to:r||e?void 0:""}],o=x(t.replace)?t.replace:[];k(n)&&o.push({from:n,to:void 0});var a=ht(o,m("from"));return ct(i,function(t){return-1===a.indexOf(t.from)}).concat(o)}(o,s,c,h),v=E(o.inherit)?!!o.inherit:!!e.inherit;B(this,{id:t,type:e,location:r,isOptional:c,dynamic:f,raw:l,squash:h,replace:p,inherit:v,array:s,config:o})}var ke=(Oe.prototype.dispose=function(){this.types={}},Oe.prototype.type=function(t,e,r){if(!E(e))return this.types[t];if(this.types.hasOwnProperty(t))throw new Error("A type named '"+t+"' has already been defined.");return this.types[t]=new _e(B({name:t},e)),r&&(this.typeQueue.push({name:t,def:r}),this.enqueue||this._flushTypeQueue()),this},Oe.prototype._flushTypeQueue=function(){for(;this.typeQueue.length;){var t=this.typeQueue.shift();if(t.pattern)throw new Error("You cannot override a type's .pattern at runtime.");B(this.types[t.name],D.$injector.invoke(t.def))}},Oe);function Oe(){this.enqueue=!0,this.typeQueue=[],this.defaultTypes=at(Oe.prototype,["hash","string","query","path","int","bool","date","json","any"]);this.types=Q(ht(this.defaultTypes,function(t,e){return new _e(B({name:e},t))}),{})}function xe(t){function e(t){return null!=t?t.toString():t}var r={encode:e,decode:e,is:h(String),pattern:/.*/,equals:function(t,e){return t==e}};return B({},r,t)}B(ke.prototype,{string:xe({}),path:xe({pattern:/[^/]*/}),query:xe({}),hash:xe({inherit:!1}),int:xe({decode:function(t){return parseInt(t,10)},is:function(t){return!C(t)&&this.decode(t.toString())===t},pattern:/-?\d+/}),bool:xe({encode:function(t){return t?1:0},decode:function(t){return 0!==parseInt(t,10)},is:h(Boolean),pattern:/0|1/}),date:xe({encode:function(t){return this.is(t)?[t.getFullYear(),("0"+(t.getMonth()+1)).slice(-2),("0"+t.getDate()).slice(-2)].join("-"):void 0},decode:function(t){if(this.is(t))return t;var e=this.capture.exec(t);return e?new Date(e[1],e[2]-1,e[3]):void 0},is:function(t){return t instanceof Date&&!isNaN(t.valueOf())},equals:function(r,n){return["getFullYear","getMonth","getDate"].reduce(function(t,e){return t&&r[e]()===n[e]()},!0)},pattern:/[0-9]{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[1-2][0-9]|3[0-1])/,capture:/([0-9]{4})-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])/}),json:xe({encode:L,decode:N,is:h(Object),equals:G,pattern:/[^/]*/}),any:xe({encode:z,decode:z,is:function(){return!0},equals:G})});var je=(Ve.prototype.$inherit=function(t,e,r){var n,i=ot(e,r),o={},a=[];for(var u in i)if(i[u]&&i[u].params&&(n=Object.keys(i[u].params)).length)for(var s in n)0<=a.indexOf(n[s])||(a.push(n[s]),o[n[s]]=this[n[s]]);return B({},o,t)},Ve);function Ve(t){void 0===t&&(t={}),B(this,t)}var He=(Ie.prototype.clone=function(){return new Ie(this)},Ie.prototype.applyRawParams=function(r){return this.paramValues=this.paramSchema.reduce(function(t,e){return Tt(t,function(t){return[t.id,t.value(r[t.id])]}(e))},{}),this},Ie.prototype.parameter=function(t){return ft(this.paramSchema,y("id",t))},Ie.prototype.equals=function(t,e){var r=this.diff(t,e);return r&&0===r.length},Ie.prototype.diff=function(t,e){if(this.state!==t.state)return!1;var r=e?e(this):this.paramSchema;return Te.changed(r,this.paramValues,t.paramValues)},Ie.clone=function(t){return t.clone()},Ie);function Ie(t){if(t instanceof Ie){var e=t;this.state=e.state,this.paramSchema=e.paramSchema.slice(),this.paramValues=B({},e.paramValues),this.resolvables=e.resolvables.slice(),this.views=e.views&&e.views.slice()}else{var r=t;this.state=r,this.paramSchema=r.parameters({inherit:!1}),this.paramValues={},this.resolvables=r.resolvables.map(function(t){return t.clone()})}}var Ae=(De.prototype.name=function(){return this._definition&&this._definition.name||this._identifier},De.prototype.identifier=function(){return this._identifier},De.prototype.params=function(){return this._params},De.prototype.$state=function(){return this._definition},De.prototype.state=function(){return this._definition&&this._definition.self},De.prototype.options=function(){return this._options},De.prototype.exists=function(){return!(!this._definition||!this._definition.self)},De.prototype.valid=function(){return!this.error()},De.prototype.error=function(){var t=this.options().relative;if(this._definition||!t)return this._definition?this._definition.self?void 0:"State '"+this.name()+"' has an invalid definition":"No such state '"+this.name()+"'";var e=t.name?t.name:t;return"Could not resolve '"+this.name()+"' from state '"+e+"'"},De.prototype.toString=function(){return"'"+this.name()+"'"+Qt(this.params())},De.prototype.withState=function(t){return new De(this._stateRegistry,t,this._params,this._options)},De.prototype.withParams=function(t,e){void 0===e&&(e=!1);var r=e?t:B({},this._params,t);return new De(this._stateRegistry,this._identifier,r,this._options)},De.prototype.withOptions=function(t,e){void 0===e&&(e=!1);var r=e?t:B({},this._options,t);return new De(this._stateRegistry,this._identifier,this._params,r)},De.isDef=function(t){return t&&t.state&&(k(t.state)||k(t.state.name))},De);function De(t,e,r,n){this._stateRegistry=t,this._identifier=e,this._identifier=e,this._params=B({},r||{}),this._options=B({},n||{}),this._definition=t.matcher.find(e,this._options.relative)}var qe=(Ue.makeTargetState=function(t,e){var r=Pt(e).state;return new Ae(t,r,e.map(m("paramValues")).reduce(it,{}),{})},Ue.buildPath=function(t){var e=t.params();return t.$state().path.map(function(t){return new He(t).applyRawParams(e)})},Ue.buildToPath=function(t,e){var r=Ue.buildPath(e);return e.options().inherit?Ue.inheritParams(t,r,Object.keys(e.params())):r},Ue.applyViewConfigs=function(i,o,e){o.filter(function(t){return K(e,t.state)}).forEach(function(e){var t=pt(e.state.views||{}),r=Ue.subPath(o,function(t){return t===e}),n=t.map(function(t){return i.createViewConfig(r,t)});e.views=n.reduce(mt,[])})},Ue.inheritParams=function(o,t,a){void 0===a&&(a=[]);var u=o.map(function(t){return t.paramSchema}).reduce(mt,[]).filter(function(t){return!t.inherit}).map(m("id"));return t.map(function(t){var e=B({},t&&t.paramValues),r=at(e,a);e=ut(e,a);var n=ut(function(t,e){var r=ft(t,y("state",e));return B({},r&&r.paramValues)}(o,t.state)||{},u),i=B(e,n,r);return new He(t.state).applyRawParams(i)})},Ue.treeChanges=function(t,n,e){for(var r,i,o,a,u,s,c=Math.min(t.length,n.length),f=0;f<c&&t[f].state!==e&&(r=t[f],i=n[f],r.equals(i,Ue.nonDynamicParams));)f++;a=(o=t).slice(0,f),u=o.slice(f);var l=a.map(function(t,e){var r=t.clone();return r.paramValues=n[e].paramValues,r});return s=n.slice(f),{from:o,to:l.concat(s),retained:a,retainedWithToParams:l,exiting:u,entering:s}},Ue.matching=function(t,e,i){var o=!1;return Ct(t,e).reduce(function(t,e){var r=e[0],n=e[1];return(o=o||!r.equals(n,i))?t:t.concat(r)},[])},Ue.equals=function(t,e,r){return t.length===e.length&&Ue.matching(t,e,r).length===t.length},Ue.subPath=function(t,e){var r=ft(t,e),n=t.indexOf(r);return-1===n?void 0:t.slice(0,n+1)},Ue.nonDynamicParams=function(t){return t.state.parameters({inherit:!1}).filter(function(t){return!t.dynamic})},Ue.paramValues=function(t){return t.reduce(function(t,e){return B(t,e.paramValues)},{})},Ue);function Ue(){}var Fe={when:{LAZY:"LAZY",EAGER:"EAGER"},async:{WAIT:"WAIT",NOWAIT:"NOWAIT"}},Ne={when:"LAZY",async:"WAIT"},Le=(Me.prototype.getPolicy=function(t){var e=this.policy||{},r=t&&t.resolvePolicy||{};return{when:e.when||r.when||Ne.when,async:e.async||r.async||Ne.async}},Me.prototype.resolve=function(e,r){var n=this,t=D.$q,i=e.findNode(this),o=i&&i.state,a=this.getPolicy(o).async,u=T(a)?a:z;return this.promise=t.when().then(function(){return t.all(e.getDependencies(n).map(function(t){return t.get(e,r)}))}).then(function(t){return n.resolveFn.apply(null,t)}).then(u).then(function(t){return n.data=t,n.resolved=!0,n.resolveFn=null,we.traceResolvableResolved(n,r),n.data})},Me.prototype.get=function(t,e){return this.promise||this.resolve(t,e)},Me.prototype.toString=function(){return"Resolvable(token: "+Qt(this.token)+", requires: ["+this.deps.map(Qt)+"])"},Me.prototype.clone=function(){return new Me(this)},Me.fromData=function(t,e){return new Me(t,function(){return e},null,null,e)},Me);function Me(t,e,r,n,i){if(this.resolved=!1,this.promise=void 0,t instanceof Me)B(this,t);else if(T(e)){if(C(t))throw new Error("new Resolvable(): token argument is required");if(!T(e))throw new Error("new Resolvable(): resolveFn argument must be a function");this.token=t,this.policy=n,this.resolveFn=e,this.deps=r||[],this.data=i,this.resolved=void 0!==i,this.promise=this.resolved?D.$q.when(this.data):void 0}else if(O(t)&&t.token&&(t.hasOwnProperty("resolveFn")||t.hasOwnProperty("data"))){var o=t;return new Me(o.token,o.resolveFn,o.deps,o.policy,o.data)}}var Be=Fe.when,Ge=[Be.EAGER,Be.LAZY],ze=[Be.EAGER],We="Native Injector",Je=(Qe.prototype.getTokens=function(){return this._path.reduce(function(t,e){return t.concat(e.resolvables.map(function(t){return t.token}))},[]).reduce(wt,[])},Qe.prototype.getResolvable=function(e){return Pt(this._path.map(function(t){return t.resolvables}).reduce(mt,[]).filter(function(t){return t.token===e}))},Qe.prototype.getPolicy=function(t){var e=this.findNode(t);return t.getPolicy(e.state)},Qe.prototype.subContext=function(e){return new Qe(qe.subPath(this._path,function(t){return t.state===e}))},Qe.prototype.addResolvables=function(t,e){var r=ft(this._path,y("state",e)),n=t.map(function(t){return t.token});r.resolvables=r.resolvables.filter(function(t){return-1===n.indexOf(t.token)}).concat(t)},Qe.prototype.resolvePath=function(t,u){var s=this;void 0===t&&(t="LAZY");var c=(K(Ge,t)?t:"LAZY")===Fe.when.EAGER?ze:Ge;function f(e,r){return function(t){return K(e,s.getPolicy(t)[r])}}we.traceResolvePath(this._path,t,u);var e=this._path.reduce(function(t,e){function r(e){return e.get(a,u).then(function(t){return{token:e.token,value:t}})}var n=e.resolvables.filter(f(c,"when")),i=n.filter(f(["NOWAIT"],"async")),o=n.filter(l(f(["NOWAIT"],"async"))),a=s.subContext(e.state);return i.forEach(r),t.concat(o.map(r))},[]);return D.$q.all(e)},Qe.prototype.injector=function(){return this._injector||(this._injector=new Ke(this))},Qe.prototype.findNode=function(e){return ft(this._path,function(t){return K(t.resolvables,e)})},Qe.prototype.getDependencies=function(e){var n=this,r=this.findNode(e),i=(qe.subPath(this._path,function(t){return t===r})||this._path).reduce(function(t,e){return t.concat(e.resolvables)},[]).filter(function(t){return t!==e});return e.deps.map(function(e){var t=i.filter(function(t){return t.token===e});if(t.length)return Pt(t);var r=n.injector().getNative(e);if(b(r))throw new Error("Could not find Dependency Injection token: "+Qt(e));return new Le(e,function(){return r},[],r)})},Qe);function Qe(t){this._path=t}var Ke=(Ye.prototype.get=function(t){var e=this.context.getResolvable(t);if(e){if("NOWAIT"===this.context.getPolicy(e).async)return e.get(this.context);if(!e.resolved)throw new Error("Resolvable async .get() not complete:"+Qt(e.token));return e.data}return this.getNative(t)},Ye.prototype.getAsync=function(t){var e=this.context.getResolvable(t);return e?e.get(this.context):D.$q.when(this.native.get(t))},Ye.prototype.getNative=function(t){return this.native&&this.native.get(t)},Ye);function Ye(t){this.context=t,this.native=this.get(We)||D.$injector}function Ze(t){return t.name}function Xe(t){return t.self.$$state=function(){return t},t.self}function tr(t){return t.parent&&t.parent.data&&(t.data=t.self.data=Q(t.parent.data,t.data)),t.data}function er(a,u){return function(t){var e=t.self;if(e&&e.url&&e.name&&e.name.match(/\.\*\*$/)){var r={};kt(e,r),r.url+="{remainder:any}",e=r}var n=t.parent,i=function(t){if(!k(t))return!1;var e="^"===t.charAt(0);return{val:e?t.substring(1):t,root:e}}(e.url),o=i?a.compile(i.val,{state:e}):e.url;if(!o)return null;if(!a.isMatcher(o))throw new Error("Invalid url '"+o+"' in state '"+t+"'");return i&&i.root?o:(n&&n.navigable||u()).url.append(o)}}function rr(t){return t.parent?t.parent.path.concat(t):[t]}function nr(t){var e=t.parent?B({},t.parent.includes):{};return e[t.name]=!0,e}function ir(t){function e(t){return t.provide||t.token}var r,n,i=g([[m("resolveFn"),function(t){return new Le(e(t),t.resolveFn,t.deps,t.policy)}],[m("useFactory"),function(t){return new Le(e(t),t.useFactory,t.deps||t.dependencies,t.policy)}],[m("useClass"),function(t){return new Le(e(t),function(){return new t.useClass},[],t.policy)}],[m("useValue"),function(t){return new Le(e(t),function(){return t.useValue},[],t.policy,t.useValue)}],[m("useExisting"),function(t){return new Le(e(t),z,[t.useExisting],t.policy)}]]),o=g([[c(m("val"),k),function(t){return new Le(t.token,z,[t.val],t.policy)}],[c(m("val"),x),function(t){return new Le(t.token,Pt(t.val),t.val.slice(0,-1),t.policy)}],[c(m("val"),T),function(t){return new Le(t.token,t.val,function(t){var e=D.$injector;return t.$inject||e&&e.annotate(t,e.strictDi)||"deferred"}(t.val),t.policy)}]]),a=g([[h(Le),function(t){return t}],[function(t){return!(!t.token||!t.resolveFn)},i],[function(t){return!(!t.provide&&!t.token||!(t.useValue||t.useFactory||t.useExisting||t.useClass))},i],[function(t){return!!(t&&t.val&&(k(t.val)||x(t.val)||T(t.val)))},o],[p(!0),function(t){throw new Error("Invalid resolve value: "+Qt(t))}]]),u=t.resolve;return(x(u)?u:(r=u,n=t.resolvePolicy||{},Object.keys(r||{}).map(function(t){return{token:t,val:r[t],deps:void 0,policy:n[t]}}))).map(a)}var or=(ar.prototype.builder=function(t,e){var r=this.builders,n=r[t]||[];return k(t)&&!E(e)?1<n.length?n:n[0]:k(t)&&T(e)?(r[t]=n,r[t].push(e),function(){return r[t].splice(r[t].indexOf(e,1))&&null}):void 0},ar.prototype.build=function(t){var e=this.matcher,r=this.builders,n=this.parentName(t);if(n&&!e.find(n,void 0,!1))return null;for(var i in r)if(r.hasOwnProperty(i)){var o=r[i].reduce(function(e,r){return function(t){return r(t,e)}},W);t[i]=o(t)}return t},ar.prototype.parentName=function(t){var e=t.name||"",r=e.split(".");if("**"===r.pop()&&r.pop(),r.length){if(t.parent)throw new Error("States that specify the 'parent:' property should not have a '.' in their name ("+e+")");return r.join(".")}return t.parent?k(t.parent)?t.parent:t.parent.name:""},ar.prototype.name=function(t){var e=t.name;if(-1!==e.indexOf(".")||!t.parent)return e;var r=k(t.parent)?t.parent:t.parent.name;return r?r+"."+e:e},ar);function ar(e,t){this.matcher=e;function r(){return e.find("")}function n(t){return""===t.name}var i=this;this.builders={name:[Ze],self:[Xe],parent:[function(t){return n(t)?null:e.find(i.parentName(t))||r()}],data:[tr],url:[er(t,r)],navigable:[function(e){return function(t){return!e(t)&&t.url?t:t.parent?t.parent.navigable:null}}(n)],params:[function(n){return function(r){var t=r.url&&r.url.parameters({inherit:!1})||[],e=pt(lt(ut(r.params||{},t.map(m("id"))),function(t,e){return n.fromConfig(e,null,r.self)}));return t.concat(e).map(function(t){return[t.id,t]}).reduce(Tt,{})}}(t.paramFactory)],views:[],path:[rr],includes:[nr],resolvables:[ir]}}var ur=(sr.create=function(t){t=sr.isStateClass(t)?new t:t;var e=Q(Q(t,sr.prototype));return t.$$state=function(){return e},e.self=t,e.__stateObjectCache={nameGlob:Ht.fromString(e.name)},e},sr.prototype.is=function(t){return this===t||this.self===t||this.fqn()===t},sr.prototype.fqn=function(){if(!(this.parent&&this.parent instanceof this.constructor))return this.name;var t=this.parent.fqn();return t?t+"."+this.name:this.name},sr.prototype.root=function(){return this.parent&&this.parent.root()||this},sr.prototype.parameters=function(e){return((e=nt(e,{inherit:!0,matchingKeys:null})).inherit&&this.parent&&this.parent.parameters()||[]).concat(pt(this.params)).filter(function(t){return!e.matchingKeys||e.matchingKeys.hasOwnProperty(t.id)})},sr.prototype.parameter=function(t,e){return void 0===e&&(e={}),this.url&&this.url.parameter(t,e)||ft(pt(this.params),y("id",t))||e.inherit&&this.parent&&this.parent.parameter(t)},sr.prototype.toString=function(){return this.fqn()},sr.isStateClass=function(t){return T(t)&&!0===t.__uiRouterState},sr.isState=function(t){return O(t.__stateObjectCache)},sr);function sr(t){return sr.create(t||{})}var cr=(fr.prototype.isRelative=function(t){return 0===(t=t||"").indexOf(".")||0===t.indexOf("^")},fr.prototype.find=function(t,e,r){if(void 0===r&&(r=!0),t||""===t){var n=k(t),i=n?t:t.name;this.isRelative(i)&&(i=this.resolvePath(i,e));var o=this._states[i];if(o&&(n||!(n||o!==t&&o.self!==t)))return o;if(n&&r){var a=pt(this._states).filter(function(t){return t.__stateObjectCache.nameGlob&&t.__stateObjectCache.nameGlob.matches(i)});return 1<a.length&&ce.error("stateMatcher.find: Found multiple matches for "+i+" using glob: ",a.map(function(t){return t.name})),a[0]}}},fr.prototype.resolvePath=function(t,e){if(!e)throw new Error("No reference point given for path '"+t+"'");for(var r=this.find(e),n=t.split("."),i=n.length,o=0,a=r;o<i;o++)if(""!==n[o]||0!==o){if("^"!==n[o])break;if(!a.parent)throw new Error("Path '"+t+"' not valid for state '"+r.name+"'");a=a.parent}else a=r;var u=n.slice(o).join(".");return a.name+(a.name&&u?".":"")+u},fr);function fr(t){this._states=t}var lr=(hr.prototype.dispose=function(){this.queue=[]},hr.prototype.register=function(t){var e=this.queue,r=ur.create(t),n=r.name;if(!k(n))throw new Error("State must have a valid name");if(this.states.hasOwnProperty(n)||K(e.map(m("name")),n))throw new Error("State '"+n+"' is already defined");return e.push(r),this.flush(),r},hr.prototype.flush=function(){for(var e=this,t=this.queue,r=this.states,n=this.builder,i=[],o=[],a={},u=function(t){return e.states.hasOwnProperty(t)&&e.states[t]},s=function(){i.length&&e.listeners.forEach(function(t){return t("registered",i.map(function(t){return t.self}))})};0<t.length;){var c=t.shift(),f=c.name,l=n.build(c),h=o.indexOf(c);if(l){var p=u(f);if(p&&p.name===f)throw new Error("State '"+f+"' is already defined");var v=u(f+".**");v&&this.router.stateRegistry.deregister(v),r[f]=c,this.attachRoute(c),0<=h&&o.splice(h,1),i.push(c)}else{var d=a[f];if(a[f]=t.length,0<=h&&d===t.length)return t.push(c),s(),r;h<0&&o.push(c),t.push(c)}}return s(),r},hr.prototype.attachRoute=function(t){if(!t.abstract&&t.url){var e=this.router.urlService.rules;e.rule(e.urlRuleFactory.create(t))}},hr);function hr(t,e,r,n){this.router=t,this.states=e,this.builder=r,this.listeners=n,this.queue=[]}var pr,vr,dr=(mr.prototype._registerRoot=function(){(this._root=this.stateQueue.register({name:"",url:"^",views:null,params:{"#":{value:null,type:"hash",dynamic:!0}},abstract:!0})).navigable=null},mr.prototype.dispose=function(){var e=this;this.stateQueue.dispose(),this.listeners=[],this.get().forEach(function(t){return e.get(t)&&e.deregister(t)})},mr.prototype.onStatesChanged=function(t){return this.listeners.push(t),function(){Z(this.listeners)(t)}.bind(this)},mr.prototype.root=function(){return this._root},mr.prototype.register=function(t){return this.stateQueue.register(t)},mr.prototype._deregisterTree=function(t){var r=this,n=this.get().map(function(t){return t.$$state()}),i=function(e){var t=n.filter(function(t){return-1!==e.indexOf(t.parent)});return 0===t.length?t:t.concat(i(t))},e=i([t]),o=[t].concat(e).reverse();return o.forEach(function(t){var e=r.router.urlService.rules;e.rules().filter(y("state",t)).forEach(function(t){return e.removeRule(t)}),delete r.states[t.name]}),o},mr.prototype.deregister=function(t){var e=this.get(t);if(!e)throw new Error("Can't deregister state; not found: "+t);var r=this._deregisterTree(e.$$state());return this.listeners.forEach(function(t){return t("deregistered",r.map(function(t){return t.self}))}),r},mr.prototype.get=function(t,e){var r=this;if(0===arguments.length)return Object.keys(this.states).map(function(t){return r.states[t].self});var n=this.matcher.find(t,e);return n&&n.self||null},mr.prototype.decorator=function(t,e){return this.builder.builder(t,e)},mr);function mr(t){this.router=t,this.states={},this.listeners=[],this.matcher=new cr(this.states),this.builder=new or(this.matcher,t.urlMatcherFactory),this.stateQueue=new lr(t,this.states,this.builder,this.listeners),this._registerRoot()}(pr=d.TransitionHookPhase||(d.TransitionHookPhase={}))[pr.CREATE=0]="CREATE",pr[pr.BEFORE=1]="BEFORE",pr[pr.RUN=2]="RUN",pr[pr.SUCCESS=3]="SUCCESS",pr[pr.ERROR=4]="ERROR",(vr=d.TransitionHookScope||(d.TransitionHookScope={}))[vr.TRANSITION=0]="TRANSITION",vr[vr.STATE=1]="STATE";var yr={current:W,transition:null,traceData:{},bind:null},gr=(wr.chain=function(t,e){return t.reduce(function(t,e){return t.then(function(){return e.invokeHook()})},e||D.$q.when())},wr.invokeHooks=function(t,e){for(var r=0;r<t.length;r++){var n=t[r].invokeHook();if(A(n)){var i=t.slice(r+1);return wr.chain(i,n).then(e)}}return e()},wr.runAllHooks=function(t){t.forEach(function(t){return t.invokeHook()})},wr.prototype.logError=function(t){this.transition.router.stateService.defaultErrorHandler()(t)},wr.prototype.invokeHook=function(){var e=this,r=this.registeredHook;if(!r._deregistered){var t=this.getNotCurrentRejection();if(t)return t;var n=this.options;we.traceHookInvocation(this,this.transition,n);var i=function(t){return r.eventType.getErrorHandler(e)(t)},o=function(t){return r.eventType.getResultHandler(e)(t)};try{var a=r.callback.call(n.bind,e.transition,e.stateContext);return!this.type.synchronous&&A(a)?a.catch(function(t){return Ft.normalize(t).toPromise()}).then(o,i):o(a)}catch(t){return i(Ft.normalize(t))}finally{r.invokeLimit&&++r.invokeCount>=r.invokeLimit&&r.deregister()}}},wr.prototype.handleHookResult=function(t){var e=this,r=this.getNotCurrentRejection();return r||(A(t)?t.then(function(t){return e.handleHookResult(t)}):(we.traceHookResult(t,this.transition,this.options),!1===t?Ft.aborted("Hook aborted transition").toPromise():h(Ae)(t)?Ft.redirected(t).toPromise():void 0))},wr.prototype.getNotCurrentRejection=function(){var t=this.transition.router;return t._disposed?Ft.aborted("UIRouter instance #"+t.$id+" has been stopped (disposed)").toPromise():this.transition._aborted?Ft.aborted().toPromise():this.isSuperseded()?Ft.superseded(this.options.current()).toPromise():void 0},wr.prototype.toString=function(){var t=this.options,e=this.registeredHook;return(R("traceData.hookType")(t)||"internal")+" context: "+(R("traceData.context.state.name")(t)||R("traceData.context")(t)||"unknown")+", "+Lt(200,zt(e.callback))},wr.HANDLE_RESULT=function(e){return function(t){return e.handleHookResult(t)}},wr.LOG_REJECTED_RESULT=function(e){return function(t){A(t)&&t.catch(function(t){return e.logError(Ft.normalize(t))})}},wr.LOG_ERROR=function(e){return function(t){return e.logError(t)}},wr.REJECT_ERROR=function(t){return function(t){return Vt(t)}},wr.THROW_ERROR=function(t){return function(t){throw t}},wr);function wr(t,e,r,n){var i=this;this.transition=t,this.stateContext=e,this.registeredHook=r,this.options=n,this.isSuperseded=function(){return i.type.hookPhase===d.TransitionHookPhase.RUN&&!i.options.transition.isActive()},this.options=nt(n,yr),this.type=r.eventType}function _r(t,e,r){var i=k(e)?[e]:e;return!!(T(i)?i:function(t){for(var e=i,r=0;r<e.length;r++){var n=new Ht(e[r]);if(n&&n.matches(t.name)||!n&&e[r]===t.name)return!0}return!1})(t,r)}var Sr=(br.prototype._matchingNodes=function(t,e,r){if(!0===e)return t;var n=t.filter(function(t){return _r(t.state,e,r)});return n.length?n:null},br.prototype._getDefaultMatchCriteria=function(){return lt(this.tranSvc._pluginapi._getPathTypes(),function(){return!0})},br.prototype._getMatchingNodes=function(o,a){var u=this,s=B(this._getDefaultMatchCriteria(),this.matchCriteria);return pt(this.tranSvc._pluginapi._getPathTypes()).reduce(function(t,e){var r=e.scope===d.TransitionHookScope.STATE,n=o[e.name]||[],i=r?n:[Pt(n)];return t[e.name]=u._matchingNodes(i,s[e.name],a),t},{})},br.prototype.matches=function(t,e){var r=this._getMatchingNodes(t,e);return pt(r).every(z)?r:null},br.prototype.deregister=function(){this.removeHookFromRegistry(this),this._deregistered=!0},br);function br(t,e,r,n,i,o){void 0===o&&(o={}),this.tranSvc=t,this.eventType=e,this.callback=r,this.matchCriteria=n,this.removeHookFromRegistry=i,this.invokeCount=0,this._deregistered=!1,this.priority=o.priority||0,this.bind=o.bind||null,this.invokeLimit=o.invokeLimit}function $r(t,i,o){var a=(t._registeredHooks=t._registeredHooks||{})[o.name]=[],u=Z(a);function e(t,e,r){void 0===r&&(r={});var n=new Sr(i,o,e,t,u,r);return a.push(n),n.deregister.bind(n)}return t[o.name]=e}var Rr=(Er.prototype.buildHooksForPhase=function(t){var e=this;return this.transition.router.transitionService._pluginapi._getEvents(t).map(function(t){return e.buildHooks(t)}).reduce(mt,[]).filter(z)},Er.prototype.buildHooks=function(o){var a=this.transition,t=a.treeChanges(),e=this.getMatchingHooks(o,t,a);if(!e)return[];var u={transition:a,current:a.options().current};return e.map(function(i){return i.matches(t,a)[o.criteriaMatchPath.name].map(function(t){var e=B({bind:i.bind,traceData:{hookType:o.name,context:t}},u),r=o.criteriaMatchPath.scope===d.TransitionHookScope.STATE?t.state.self:null,n=new gr(a,r,i,e);return{hook:i,node:t,transitionHook:n}})}).reduce(mt,[]).sort(function(i){return void 0===i&&(i=!1),function(t,e){var r=i?-1:1,n=(t.node.state.path.length-e.node.state.path.length)*r;return 0!=n?n:e.hook.priority-t.hook.priority}}(o.reverseSort)).map(function(t){return t.transitionHook})},Er.prototype.getMatchingHooks=function(e,r,n){var t=e.hookPhase===d.TransitionHookPhase.CREATE,i=this.transition.router.transitionService;return(t?[i]:[this.transition,i]).map(function(t){return t.getHooks(e.name)}).filter(bt(x,"broken event named: "+e.name)).reduce(mt,[]).filter(function(t){return t.matches(r,n)})},Er);function Er(t){this.transition=t}var Cr=m("self"),Tr=(Pr.prototype.onBefore=function(t,e,r){},Pr.prototype.onStart=function(t,e,r){},Pr.prototype.onExit=function(t,e,r){},Pr.prototype.onRetain=function(t,e,r){},Pr.prototype.onEnter=function(t,e,r){},Pr.prototype.onFinish=function(t,e,r){},Pr.prototype.onSuccess=function(t,e,r){},Pr.prototype.onError=function(t,e,r){},Pr.prototype.createTransitionHookRegFns=function(){var e=this;this.router.transitionService._pluginapi._getEvents().filter(function(t){return t.hookPhase!==d.TransitionHookPhase.CREATE}).forEach(function(t){return $r(e,e.router.transitionService,t)})},Pr.prototype.getHooks=function(t){return this._registeredHooks[t]},Pr.prototype.applyViewConfigs=function(t){var e=this._treeChanges.entering.map(function(t){return t.state});qe.applyViewConfigs(t.transitionService.$view,this._treeChanges.to,e)},Pr.prototype.$from=function(){return Pt(this._treeChanges.from).state},Pr.prototype.$to=function(){return Pt(this._treeChanges.to).state},Pr.prototype.from=function(){return this.$from().self},Pr.prototype.to=function(){return this.$to().self},Pr.prototype.targetState=function(){return this._targetState},Pr.prototype.is=function(t){return t instanceof Pr?this.is({to:t.$to().name,from:t.$from().name}):!(t.to&&!_r(this.$to(),t.to,this)||t.from&&!_r(this.$from(),t.from,this))},Pr.prototype.params=function(t){return void 0===t&&(t="to"),Object.freeze(this._treeChanges[t].map(m("paramValues")).reduce(it,{}))},Pr.prototype.paramsChanged=function(){var t=this.params("from"),r=this.params("to"),e=[].concat(this._treeChanges.to).concat(this._treeChanges.from).map(function(t){return t.paramSchema}).reduce(yt,[]).reduce(wt,[]);return Te.changed(e,t,r).reduce(function(t,e){return t[e.id]=r[e.id],t},{})},Pr.prototype.injector=function(e,t){void 0===t&&(t="to");var r=this._treeChanges[t];return e&&(r=qe.subPath(r,function(t){return t.state===e||t.state.name===e})),new Je(r).injector()},Pr.prototype.getResolveTokens=function(t){return void 0===t&&(t="to"),new Je(this._treeChanges[t]).getTokens()},Pr.prototype.addResolvable=function(t,e){void 0===e&&(e=""),t=h(Le)(t)?t:new Le(t);var r="string"==typeof e?e:e.name,n=this._treeChanges.to,i=ft(n,function(t){return t.state.name===r});new Je(n).addResolvables([t],i.state)},Pr.prototype.redirectedFrom=function(){return this._options.redirectedFrom||null},Pr.prototype.originalTransition=function(){var t=this.redirectedFrom();return t&&t.originalTransition()||this},Pr.prototype.options=function(){return this._options},Pr.prototype.entering=function(){return ht(this._treeChanges.entering,m("state")).map(Cr)},Pr.prototype.exiting=function(){return ht(this._treeChanges.exiting,m("state")).map(Cr).reverse()},Pr.prototype.retained=function(){return ht(this._treeChanges.retained,m("state")).map(Cr)},Pr.prototype.views=function(t,e){void 0===t&&(t="entering");var r=this._treeChanges[t];return(r=e?r.filter(y("state",e)):r).map(m("views")).filter(z).reduce(mt,[])},Pr.prototype.treeChanges=function(t){return t?this._treeChanges[t]:this._treeChanges},Pr.prototype.redirect=function(t){for(var e=1,r=this;null!=(r=r.redirectedFrom());)if(20<++e)throw new Error("Too many consecutive Transition redirects (20+)");var n={redirectedFrom:this,source:"redirect"};"url"===this.options().source&&!1!==t.options().location&&(n.location="replace");var i=B({},this.options(),t.options(),n);t=t.withOptions(i,!0);var o,a=this.router.transitionService.create(this._treeChanges.from,t),u=this._treeChanges.entering,s=a._treeChanges.entering;return qe.matching(s,u,qe.nonDynamicParams).filter(l((o=t.options().reloadState,function(t){return o&&t.state.includes[o.name]}))).forEach(function(t,e){t.resolvables=u[e].resolvables}),a},Pr.prototype._changedParams=function(){var t=this._treeChanges;if(!(this._options.reload||t.exiting.length||t.entering.length||t.to.length!==t.from.length||Ct(t.to,t.from).map(function(t){return t[0].state!==t[1].state}).reduce(dt,!1))){var e=t.to.map(function(t){return t.paramSchema}),r=[t.to,t.from].map(function(t){return t.map(function(t){return t.paramValues})});return Ct(e,r[0],r[1]).map(function(t){var e=t[0],r=t[1],n=t[2];return Te.changed(e,r,n)}).reduce(mt,[])}},Pr.prototype.dynamic=function(){var t=this._changedParams();return!!t&&t.map(function(t){return t.dynamic}).reduce(dt,!1)},Pr.prototype.ignored=function(){return!!this._ignoredReason()},Pr.prototype._ignoredReason=function(){function t(t,e){if(t.length!==e.length)return!1;var r=qe.matching(t,e);return t.length===r.filter(function(t){return!n||!t.state.includes[n.name]}).length}var e=this.router.globals.transition,n=this._options.reloadState,r=this.treeChanges(),i=e&&e.treeChanges();return i&&t(i.to,r.to)&&t(i.exiting,r.exiting)?"SameAsPending":0===r.exiting.length&&0===r.entering.length&&t(r.from,r.to)?"SameAsCurrent":void 0},Pr.prototype.run=function(){function e(t){return r._hookBuilder.buildHooksForPhase(t)}var r=this,n=gr.runAllHooks,t=e(d.TransitionHookPhase.BEFORE);return gr.invokeHooks(t,function(){var t=r.router.globals;return t.lastStartedTransitionId=r.$id,t.transition=r,t.transitionHistory.enqueue(r),we.traceTransitionStart(r),D.$q.when(void 0)}).then(function(){var t=e(d.TransitionHookPhase.RUN);return gr.invokeHooks(t,function(){return D.$q.when(void 0)})}).then(function(){we.traceSuccess(r.$to(),r),r.success=!0,r._deferred.resolve(r.to()),n(e(d.TransitionHookPhase.SUCCESS))},function(t){we.traceError(t,r),r.success=!1,r._deferred.reject(t),r._error=t,n(e(d.TransitionHookPhase.ERROR))}),this.promise},Pr.prototype.valid=function(){return!this.error()||void 0!==this.success},Pr.prototype.abort=function(){b(this.success)&&(this._aborted=!0)},Pr.prototype.error=function(){var t=this.$to();if(t.self.abstract)return Ft.invalid("Cannot transition to abstract state '"+t.name+"'");var e=t.parameters(),r=this.params(),n=e.filter(function(t){return!t.validates(r[t.id])});if(n.length){var i=n.map(function(t){return"["+t.id+":"+Qt(r[t.id])+"]"}).join(", "),o="The following parameter values are not valid for state '"+t.name+"': "+i;return Ft.invalid(o)}return!1===this.success?this._error:void 0},Pr.prototype.toString=function(){function t(t){return null!==t["#"]&&void 0!==t["#"]?t:ut(t,["#"])}var e=this.from(),r=this.to();return"Transition#"+this.$id+"( '"+(O(e)?e.name:e)+"'"+Qt(t(this._treeChanges.from.map(m("paramValues")).reduce(it,{})))+" -> "+(this.valid()?"":"(X) ")+"'"+(O(r)?r.name:r)+"'"+Qt(t(this.params()))+" )"},Pr.diToken=Pr);function Pr(t,e,r){var n=this;if(this._deferred=D.$q.defer(),this.promise=this._deferred.promise,this._registeredHooks={},this._hookBuilder=new Rr(this),this.isActive=function(){return n.router.globals.transition===n},this.router=r,!(this._targetState=e).valid())throw new Error(e.error());this._options=B({current:p(this)},e.options()),this.$id=r.transitionService._transitionCount++;var i=qe.buildToPath(t,e);this._treeChanges=qe.treeChanges(t,i,this._options.reloadState),this.createTransitionHookRegFns();var o=this._hookBuilder.buildHooksForPhase(d.TransitionHookPhase.CREATE);gr.invokeHooks(o,function(){return null}),this.applyViewConfigs(r)}function kr(t,e){var r=["",""],n=t.replace(/[\\\[\]\^$*+?.()|{}]/g,"\\$&");if(!e)return n;switch(e.squash){case!1:r=["(",")"+(e.isOptional?"?":"")];break;case!0:n=n.replace(/\/$/,""),r=["(?:/(",")|/)?"];break;default:r=["("+e.squash+"|",")?"]}return n+r[0]+e.type.pattern.source+r[1]}var Or=ne("/"),xr={state:{params:{}},strict:!0,caseInsensitive:!0},jr=(Vr.encodeDashes=function(t){return encodeURIComponent(t).replace(/-/g,function(t){return"%5C%"+t.charCodeAt(0).toString(16).toUpperCase()})},Vr.pathSegmentsAndParams=function(t){return Ct(t._segments,t._params.filter(function(t){return t.location===d.DefType.PATH}).concat(void 0)).reduce(mt,[]).filter(function(t){return""!==t&&E(t)})},Vr.queryParams=function(t){return t._params.filter(function(t){return t.location===d.DefType.SEARCH})},Vr.compare=function(t,e){function r(t){return t._cache.weights=t._cache.weights||function(t){return t._cache.segments=t._cache.segments||t._cache.path.map(Vr.pathSegmentsAndParams).reduce(mt,[]).reduce(ie,[]).map(function(t){return k(t)?Or(t):t}).reduce(mt,[])}(t).map(function(t){return"/"===t?1:k(t)?2:t instanceof Te?3:void 0})}var n=r(t),i=r(e);!function(t,e,r){for(var n=Math.max(t.length,e.length);t.length<n;)t.push(r);for(;e.length<n;)e.push(r)}(n,i,0);var o,a,u=Ct(n,i);for(a=0;a<u.length;a++)if(0!=(o=u[a][0]-u[a][1]))return o;return 0},Vr.prototype.append=function(t){return this._children.push(t),t._cache={path:this._cache.path.concat(t),parent:this,pattern:null},t},Vr.prototype.isRoot=function(){return this._cache.path[0]===this},Vr.prototype.toString=function(){return this.pattern},Vr.prototype.exec=function(t,n,e,r){var i=this;void 0===n&&(n={});var o=function(t,e,r){return t[e]=t[e]||r()}(this._cache,"pattern",function(){return new RegExp(["^",_t(i._cache.path.map(m("_compiled"))).join(""),!1===i.config.strict?"/?":"","$"].join(""),i.config.caseInsensitive?"i":void 0)}).exec(t);if(!o)return null;var a=this.parameters(),u=a.filter(function(t){return!t.isSearch()}),s=a.filter(function(t){return t.isSearch()}),c=this._cache.path.map(function(t){return t._segments.length-1}).reduce(function(t,e){return t+e}),f={};if(c!==o.length-1)throw new Error("Unbalanced capture group in route '"+this.pattern+"'");for(var l=0;l<c;l++){for(var h=u[l],p=o[l+1],v=0;v<h.replace.length;v++)h.replace[v].from===p&&(p=h.replace[v].to);p&&!0===h.array&&(p=ht(ht(d(p).split(/-(?!\\)/),d),function(t){return t.replace(/\\-/g,"-")}).reverse()),E(p)&&(p=h.type.decode(p)),f[h.id]=h.value(p)}function d(t){return t.split("").reverse().join("")}return s.forEach(function(t){for(var e=n[t.id],r=0;r<t.replace.length;r++)t.replace[r].from===e&&(e=t.replace[r].to);E(e)&&(e=t.type.decode(e)),f[t.id]=t.value(e)}),e&&(f["#"]=e),f},Vr.prototype.parameters=function(t){return void 0===t&&(t={}),!1===t.inherit?this._params:_t(this._cache.path.map(function(t){return t._params}))},Vr.prototype.parameter=function(n,t){var i=this;void 0===t&&(t={});var e=this._cache.parent;return function(){for(var t=0,e=i._params;t<e.length;t++){var r=e[t];if(r.id===n)return r}}()||!1!==t.inherit&&e&&e.parameter(n,t)||null},Vr.prototype.validates=function(e){return e=e||{},this.parameters().filter(function(t){return e.hasOwnProperty(t.id)}).map(function(t){return function(t,e){return!t||t.validates(e)}(t,e[t.id])}).reduce(vt,!0)},Vr.prototype.format=function(a){void 0===a&&(a={});var t=this._cache.path,e=t.map(Vr.pathSegmentsAndParams).reduce(mt,[]).map(function(t){return k(t)?t:n(t)}),r=t.map(Vr.queryParams).reduce(mt,[]).map(n);if(e.concat(r).filter(function(t){return!1===t.isValid}).length)return null;function n(t){var e=t.value(a[t.id]),r=t.validates(e),n=t.isDefaultValue(e),i=!!n&&t.squash,o=t.type.encode(e);return{param:t,value:e,isValid:r,isDefaultValue:n,squash:i,encoded:o}}var i=e.reduce(function(t,e){if(k(e))return t+e;var r=e.squash,n=e.encoded,i=e.param;return!0===r?t.match(/\/$/)?t.slice(0,-1):t:k(r)?t+r:!1!==r?t:null==n?t:x(n)?t+ht(n,Vr.encodeDashes).join("-"):i.raw?t+n:t+encodeURIComponent(n)},""),o=r.map(function(t){var e=t.param,r=t.squash,n=t.encoded,i=t.isDefaultValue;if(!(null==n||i&&!1!==r)&&(x(n)||(n=[n]),0!==n.length))return e.raw||(n=ht(n,encodeURIComponent)),n.map(function(t){return e.id+"="+t})}).filter(z).reduce(mt,[]).join("&");return i+(o?"?"+o:"")+(a["#"]?"#"+a["#"]:"")},Vr.nameValidator=/^\w+([-.]+\w+)*(?:\[\])?$/,Vr);function Vr(o,a,t,e){var u=this;this._cache={path:[this]},this._children=[],this._params=[],this._segments=[],this._compiled=[],this.config=e=nt(e,xr),this.pattern=o;for(var r,n,i,s=/([:*])([\w\[\]]+)|\{([\w\[\]]+)(?:\:\s*((?:[^{}\\]+|\\.|\{(?:[^{}\\]+|\\.)*\})+))?\}/g,c=/([:]?)([\w\[\].-]+)|\{([\w\[\].-]+)(?:\:\s*((?:[^{}\\]+|\\.|\{(?:[^{}\\]+|\\.)*\})+))?\}/g,f=[],l=0,h=function(t){if(!Vr.nameValidator.test(t))throw new Error("Invalid parameter name '"+t+"' in pattern '"+o+"'");if(ft(u._params,y("id",t)))throw new Error("Duplicate parameter name '"+t+"' in pattern '"+o+"'")},p=function(t,e){var r,n=t[2]||t[3],i=e?t[4]:t[4]||("*"===t[1]?"[\\s\\S]*":null);return{id:n,regexp:i,segment:o.substring(l,t.index),type:i?a.type(i)||(r=i,Q(a.type(e?"query":"path"),{pattern:new RegExp(r,u.config.caseInsensitive?"i":void 0)})):null}};(r=s.exec(o))&&!(0<=(n=p(r,!1)).segment.indexOf("?"));)h(n.id),this._params.push(t.fromPath(n.id,n.type,e.state)),this._segments.push(n.segment),f.push([n.segment,Pt(this._params)]),l=s.lastIndex;var v=(i=o.substring(l)).indexOf("?");if(0<=v){var d=i.substring(v);if(i=i.substring(0,v),0<d.length)for(l=0;r=c.exec(d);)h((n=p(r,!0)).id),this._params.push(t.fromSearch(n.id,n.type,e.state)),l=s.lastIndex}this._segments.push(i),this._compiled=f.map(function(t){return kr.apply(null,t)}).concat(kr(i))}var Hr=function(){return(Hr=Object.assign||function(t){for(var e,r=1,n=arguments.length;r<n;r++)for(var i in e=arguments[r])Object.prototype.hasOwnProperty.call(e,i)&&(t[i]=e[i]);return t}).apply(this,arguments)},Ir=(Ar.prototype.fromConfig=function(t,e,r){return new Te(t,e,d.DefType.CONFIG,this.router.urlService.config,r)},Ar.prototype.fromPath=function(t,e,r){return new Te(t,e,d.DefType.PATH,this.router.urlService.config,r)},Ar.prototype.fromSearch=function(t,e,r){return new Te(t,e,d.DefType.SEARCH,this.router.urlService.config,r)},Ar);function Ar(t){this.router=t}var Dr=(qr.prototype.compile=function(t,e){var r=this.router.urlService.config,n=e&&!e.state&&e.params;e=n?Hr({state:{params:n}},e):e;var i={strict:r._isStrictMode,caseInsensitive:r._isCaseInsensitive};return new jr(t,r.paramTypes,this.paramFactory,B(i,e))},qr.prototype.isMatcher=function(r){if(!O(r))return!1;var n=!0;return M(jr.prototype,function(t,e){T(t)&&(n=n&&E(r[e])&&T(r[e]))}),n},qr.prototype.$get=function(){var t=this.router.urlService.config;return t.paramTypes.enqueue=!1,t.paramTypes._flushTypeQueue(),this},qr);function qr(t){var n=this;this.router=t,this.paramFactory=new Ir(this.router),this.caseInsensitive=function(t){return n.router.urlService.config.caseInsensitive(t)},this.defaultSquashPolicy=function(t){return n.router.urlService.config.defaultSquashPolicy(t)},this.strictMode=function(t){return n.router.urlService.config.strictMode(t)},this.type=function(t,e,r){return n.router.urlService.config.type(t,e,r)||n},B(this,{UrlMatcher:jr,Param:Te})}var Ur=(Fr.prototype.compile=function(t){return this.router.urlMatcherFactory.compile(t)},Fr.prototype.create=function(t,e){var r=this,n=ur.isState,i=g([[k,function(t){return i(r.compile(t))}],[h(jr),function(t){return r.fromUrlMatcher(t,e)}],[n,function(t){return r.fromState(t,r.router)}],[h(RegExp),function(t){return r.fromRegExp(t,e)}],[T,function(t){return new Nr(t,e)}]]),o=i(t);if(!o)throw new Error("invalid 'what' in when()");return o},Fr.prototype.fromUrlMatcher=function(r,e){var t=e;k(e)&&(e=this.router.urlMatcherFactory.compile(e)),h(jr)(e)&&(t=function(t){return e.format(t)});var n={urlMatcher:r,matchPriority:function(e){var t=r.parameters().filter(function(t){return t.isOptional});return t.length?t.filter(function(t){return e[t.id]}).length/t.length:1e-6},type:"URLMATCHER"};return B(new Nr(function(t){var e=r.exec(t.path,t.search,t.hash);return r.validates(e)&&e},t),n)},Fr.prototype.fromState=function(n,i){var t={state:n,type:"STATE"};return B(this.fromUrlMatcher(n.url,function(t){var e=i.stateService,r=i.globals;e.href(n,t)!==e.href(r.current,r.params)&&e.transitionTo(n,t,{inherit:!0,source:"url"})}),t)},Fr.prototype.fromRegExp=function(e,t){if(e.global||e.sticky)throw new Error("Rule RegExp must not be global or sticky");var r=k(t)?function(r){return t.replace(/\$(\$|\d{1,2})/,function(t,e){return r["$"===e?0:Number(e)]})}:t,n={regexp:e,type:"REGEXP"};return B(new Nr(function(t){return e.exec(t.path)},r),n)},Fr.isUrlRule=function(e){return e&&["type","match","handler"].every(function(t){return E(e[t])})},Fr);function Fr(t){this.router=t}var Nr=function(t,e){var r=this;this.match=t,this.type="RAW",this.matchPriority=function(t){return 0-r.$id},this.handler=e||z};var Lr=(Mr.prototype.update=function(t){var e=this.router.locationService;t?this.location=e.url():e.url()!==this.location&&e.url(this.location,!0)},Mr.prototype.push=function(t,e,r){var n=r&&!!r.replace;this.router.urlService.url(t.format(e||{}),n)},Mr.prototype.href=function(t,e,r){var n=t.format(e);if(null==n)return null;r=r||{absolute:!1};var i=this.router.urlService.config,o=i.html5Mode();if(o||null===n||(n="#"+i.hashPrefix()+n),n=function(t,e,r,n){return"/"===n?t:e?Yt(n)+t:r?n.slice(1)+t:t}(n,o,r.absolute,i.baseHref()),!r.absolute||!n)return n;var a=!o&&n?"/":"",u=i.port(),s=80===u||443===u?"":":"+u;return[i.protocol(),"://",i.host(),s,a,n].join("")},Object.defineProperty(Mr.prototype,"interceptDeferred",{get:function(){return this.router.urlService.interceptDeferred},enumerable:!0,configurable:!0}),Mr);function Mr(t){var n=this;this.router=t,this.sync=function(t){return n.router.urlService.sync(t)},this.listen=function(t){return n.router.urlService.listen(t)},this.deferIntercept=function(t){return n.router.urlService.deferIntercept(t)},this.match=function(t){return n.router.urlService.match(t)},this.initial=function(t){return n.router.urlService.rules.initial(t)},this.otherwise=function(t){return n.router.urlService.rules.otherwise(t)},this.removeRule=function(t){return n.router.urlService.rules.removeRule(t)},this.rule=function(t){return n.router.urlService.rules.rule(t)},this.rules=function(){return n.router.urlService.rules.rules()},this.sort=function(t){return n.router.urlService.rules.sort(t)},this.when=function(t,e,r){return n.router.urlService.rules.when(t,e,r)},this.urlRuleFactory=new Ur(t)}var Br=(Gr.normalizeUIViewTarget=function(t,e){void 0===e&&(e="");var r=e.split("@"),n=r[0]||"$default",i=k(r[1])?r[1]:"^",o=/^(\^(?:\.\^)*)\.(.*$)/.exec(n);return o&&(i=o[1],n=o[2]),"!"===n.charAt(0)&&(n=n.substr(1),i=""),/^(\^(?:\.\^)*)$/.exec(i)?i=i.split(".").reduce(function(t,e){return t.parent},t).name:"."===i&&(i=t.name),{uiViewName:n,uiViewContextAnchor:i}},Gr.prototype._rootViewContext=function(t){return this._rootContext=t||this._rootContext},Gr.prototype._viewConfigFactory=function(t,e){this._viewConfigFactories[t]=e},Gr.prototype.createViewConfig=function(t,e){var r=this._viewConfigFactories[e.$type];if(!r)throw new Error("ViewService: No view config factory registered for type "+e.$type);var n=r(t,e);return x(n)?n:[n]},Gr.prototype.deactivateViewConfig=function(t){we.traceViewServiceEvent("<- Removing",t),Z(this._viewConfigs,t)},Gr.prototype.activateViewConfig=function(t){we.traceViewServiceEvent("-> Registering",t),this._viewConfigs.push(t)},Gr.prototype.sync=function(){var r=this,n=this._uiViews.map(function(t){return[t.fqn,t]}).reduce(Tt,{});function i(t){for(var e=t.viewDecl.$context,r=0;++r&&e.parent;)e=e.parent;return r}var o=s(function(t,e,r,n){return e*(t(r)-t(n))}),t=this._uiViews.sort(o(function(t){var e=function(t){return t&&t.parent?e(t.parent)+1:1};return 1e4*t.fqn.split(".").length+e(t.creationContext)},1)).map(function(t){var e=r._viewConfigs.filter(Gr.matches(n,t));return 1<e.length&&e.sort(o(i,-1)),{uiView:t,viewConfig:e[0]}}),e=t.map(function(t){return t.viewConfig}),a=this._viewConfigs.filter(function(t){return!K(e,t)}).map(function(t){return{uiView:void 0,viewConfig:t}});t.forEach(function(t){-1!==r._uiViews.indexOf(t.uiView)&&t.uiView.configUpdated(t.viewConfig)});var u=t.concat(a);this._listeners.forEach(function(t){return t(u)}),we.traceViewSync(u)},Gr.prototype.registerUIView=function(e){we.traceViewServiceUIViewEvent("-> Registering",e);var t=this._uiViews;return t.filter(function(t){return t.fqn===e.fqn&&t.$type===e.$type}).length&&we.traceViewServiceUIViewEvent("!!!! duplicate uiView named:",e),t.push(e),this.sync(),function(){-1!==t.indexOf(e)?(we.traceViewServiceUIViewEvent("<- Deregistering",e),Z(t)(e)):we.traceViewServiceUIViewEvent("Tried removing non-registered uiView",e)}},Gr.prototype.available=function(){return this._uiViews.map(m("fqn"))},Gr.prototype.active=function(){return this._uiViews.filter(m("$config")).map(m("name"))},Gr.matches=function(u,s){return function(t){if(s.$type!==t.viewDecl.$type)return!1;var e=t.viewDecl,r=e.$uiViewName.split("."),n=s.fqn.split(".");if(!G(r,n.slice(0-r.length)))return!1;var i=1-r.length||void 0,o=n.slice(0,i).join("."),a=u[o].creationContext;return e.$uiViewContextAnchor===(a&&a.name)}},Gr);function Gr(t){var r=this;this.router=t,this._uiViews=[],this._viewConfigs=[],this._viewConfigFactories={},this._listeners=[],this._pluginapi={_rootViewContext:this._rootViewContext.bind(this),_viewConfigFactory:this._viewConfigFactory.bind(this),_registeredUIView:function(e){return ft(r._uiViews,function(t){return r.router.$id+"."+t.id===e})},_registeredUIViews:function(){return r._uiViews},_activeViewConfigs:function(){return r._viewConfigs},_onSync:function(t){return r._listeners.push(t),function(){return Z(r._listeners,t)}}}}var zr=(Wr.prototype.dispose=function(){this.transitionHistory.clear(),this.successfulTransitions.clear(),this.transition=null},Wr);function Wr(){this.params=new je,this.lastStartedTransitionId=-1,this.transitionHistory=new Dt([],1),this.successfulTransitions=new Dt([],1)}var Jr;function Qr(t){if(!(T(t)||k(t)||h(Ae)(t)||Ae.isDef(t)))throw new Error("'handler' must be a string, function, TargetState, or have a state: 'newtarget' property");return T(t)?t:p(t)}Jr=function(t,e){var r=function(t,e){return(e.priority||0)-(t.priority||0)}(t,e);return 0!==r?r:0!==(r=function(t,e){var r={STATE:4,URLMATCHER:4,REGEXP:3,RAW:2,OTHER:1};return(r[t.type]||0)-(r[e.type]||0)}(t,e))?r:0!==(r=function(t,e){return t.urlMatcher&&e.urlMatcher?jr.compare(t.urlMatcher,e.urlMatcher):0}(t,e))?r:function(t,e){var r={STATE:!0,URLMATCHER:!0};return r[t.type]&&r[e.type]?0:(t.$id||0)-(e.$id||0)}(t,e)};var Kr=(Yr.prototype.dispose=function(t){this._rules=[],delete this._otherwiseFn},Yr.prototype.initial=function(t){var e=Qr(t);this.rule(this.urlRuleFactory.create(function(t,e){return 0===e.globals.transitionHistory.size()&&!!/^\/?$/.exec(t.path)},e))},Yr.prototype.otherwise=function(t){var e=Qr(t);this._otherwiseFn=this.urlRuleFactory.create(p(!0),e),this._sorted=!1},Yr.prototype.removeRule=function(t){Z(this._rules,t)},Yr.prototype.rule=function(t){var e=this;if(!Ur.isUrlRule(t))throw new Error("invalid rule");return t.$id=this._id++,t.priority=t.priority||0,this._rules.push(t),this._sorted=!1,function(){return e.removeRule(t)}},Yr.prototype.rules=function(){return this.ensureSorted(),this._rules.concat(this._otherwiseFn?[this._otherwiseFn]:[])},Yr.prototype.sort=function(t){for(var e=this.stableSort(this._rules,this._sortFn=t||this._sortFn),r=0,n=0;n<e.length;n++)e[n]._group=r,n<e.length-1&&0!==this._sortFn(e[n],e[n+1])&&r++;this._rules=e,this._sorted=!0},Yr.prototype.ensureSorted=function(){this._sorted||this.sort()},Yr.prototype.stableSort=function(t,n){var e=t.map(function(t,e){return{elem:t,idx:e}});return e.sort(function(t,e){var r=n(t.elem,e.elem);return 0===r?t.idx-e.idx:r}),e.map(function(t){return t.elem})},Yr.prototype.when=function(t,e,r){var n=this.urlRuleFactory.create(t,e);return E(r&&r.priority)&&(n.priority=r.priority),this.rule(n),n},Yr);function Yr(t){this.router=t,this._sortFn=Jr,this._rules=[],this._id=0,this.urlRuleFactory=new Ur(t)}var Zr=(Xr.prototype.caseInsensitive=function(t){return this._isCaseInsensitive=E(t)?t:this._isCaseInsensitive},Xr.prototype.defaultSquashPolicy=function(t){if(E(t)&&!0!==t&&!1!==t&&!k(t))throw new Error("Invalid squash policy: "+t+". Valid policies: false, true, arbitrary-string");return this._defaultSquashPolicy=E(t)?t:this._defaultSquashPolicy},Xr.prototype.strictMode=function(t){return this._isStrictMode=E(t)?t:this._isStrictMode},Xr.prototype.type=function(t,e,r){var n=this.paramTypes.type(t,e,r);return E(e)?this:n},Xr);function Xr(t){var e=this;this.router=t,this.paramTypes=new ke,this._isCaseInsensitive=!1,this._isStrictMode=!0,this._defaultSquashPolicy=!1,this.dispose=function(){return e.paramTypes.dispose()},this.baseHref=function(){return e.router.locationConfig.baseHref()},this.hashPrefix=function(t){return e.router.locationConfig.hashPrefix(t)},this.host=function(){return e.router.locationConfig.host()},this.html5Mode=function(){return e.router.locationConfig.html5Mode()},this.port=function(){return e.router.locationConfig.port()},this.protocol=function(){return e.router.locationConfig.protocol()}}var tn=(en.prototype.dispose=function(){this.listen(!1),this.rules.dispose()},en.prototype.parts=function(){return{path:this.path(),search:this.search(),hash:this.hash()}},en.prototype.sync=function(t){if(!t||!t.defaultPrevented){var e=this.router,r=e.urlService,n=e.stateService,i={path:r.path(),search:r.search(),hash:r.hash()},o=this.match(i);g([[k,function(t){return r.url(t,!0)}],[Ae.isDef,function(t){return n.go(t.state,t.params,t.options)}],[h(Ae),function(t){return n.go(t.state(),t.params(),t.options())}]])(o&&o.rule.handler(o.match,i,this.router))}},en.prototype.listen=function(t){var e=this;if(!1!==t)return this._stopListeningFn=this._stopListeningFn||this.router.urlService.onChange(function(t){return e.sync(t)});this._stopListeningFn&&this._stopListeningFn(),delete this._stopListeningFn},en.prototype.deferIntercept=function(t){void 0===t&&(t=!0),this.interceptDeferred=t},en.prototype.match=function(t){var e=this;t=B({path:"",search:{},hash:""},t);for(var r,n,i,o=this.rules.rules(),a=0;a<o.length&&(!r||r.rule._group===o[a]._group);a++){var u=(n=o[a],(i=n.match(t,e.router))&&{match:i,rule:n,weight:n.matchPriority(i)});r=!r||u&&u.weight>r.weight?u:r}return r},en);function en(t){var n=this;this.router=t,this.interceptDeferred=!1,this.rules=new Kr(this.router),this.config=new Zr(this.router),this.url=function(t,e,r){return n.router.locationService.url(t,e,r)},this.path=function(){return n.router.locationService.path()},this.search=function(){return n.router.locationService.search()},this.hash=function(){return n.router.locationService.hash()},this.onChange=function(t){return n.router.locationService.onChange(t)}}var rn=0,nn=I("LocationServices",["url","path","search","hash","onChange"]),on=I("LocationConfig",["port","protocol","host","baseHref","html5Mode","hashPrefix"]),an=(un.prototype.disposable=function(t){this._disposables.push(t)},un.prototype.dispose=function(t){var e=this;t&&T(t.dispose)?t.dispose(this):(this._disposed=!0,this._disposables.slice().forEach(function(t){try{"function"==typeof t.dispose&&t.dispose(e),Z(e._disposables,t)}catch(t){}}))},un.prototype.plugin=function(t,e){void 0===e&&(e={});var r=new t(this,e);if(!r.name)throw new Error("Required property `name` missing on plugin: "+r);return this._disposables.push(r),this._plugins[r.name]=r},un.prototype.getPlugin=function(t){return t?this._plugins[t]:pt(this._plugins)},un);function un(t,e){void 0===t&&(t=nn),void 0===e&&(e=on),this.locationService=t,this.locationConfig=e,this.$id=rn++,this._disposed=!1,this._disposables=[],this.trace=we,this.viewService=new Br(this),this.globals=new zr,this.transitionService=new kn(this),this.urlMatcherFactory=new Dr(this),this.urlRouter=new Lr(this),this.urlService=new tn(this),this.stateRegistry=new dr(this),this.stateService=new xn(this),this._plugins={},this.viewService._pluginapi._rootViewContext(this.stateRegistry.root()),this.globals.$current=this.stateRegistry.root(),this.globals.current=this.globals.$current.self,this.disposable(this.globals),this.disposable(this.stateService),this.disposable(this.stateRegistry),this.disposable(this.transitionService),this.disposable(this.urlService),this.disposable(t),this.disposable(e)}function sn(e){e.addResolvable(Le.fromData(an,e.router),""),e.addResolvable(Le.fromData(Tr,e),""),e.addResolvable(Le.fromData("$transition$",e),""),e.addResolvable(Le.fromData("$stateParams",e.params()),""),e.entering().forEach(function(t){e.addResolvable(Le.fromData("$state$",t),t)})}function cn(t){function e(t){return ln(t.token)?Le.fromData(t.token,null):t}pt(t.treeChanges()).reduce(mt,[]).reduce(wt,[]).forEach(function(t){t.resolvables=t.resolvables.map(e)})}function fn(e){var t=e.to().redirectTo;if(t){var r=e.router.stateService;return T(t)?D.$q.when(t(e)).then(n):n(t)}function n(t){if(t)return t instanceof Ae?t:k(t)?r.target(t,e.params(),e.options()):t.state||t.params?r.target(t.state||e.to(),t.params||e.params(),e.options()):void 0}}var ln=K(["$transition$",Tr]);function hn(r){return function(t,e){return(0,e.$$state()[r])(t,e)}}function pn(t){return new Je(t.treeChanges().to).resolvePath("EAGER",t).then(W)}function vn(t,e){return new Je(t.treeChanges().to).subContext(e.$$state()).resolvePath("LAZY",t).then(W)}function dn(t){return new Je(t.treeChanges().to).resolvePath("LAZY",t).then(W)}function mn(t){var e=D.$q,r=t.views("entering");if(r.length)return e.all(r.map(function(t){return e.when(t.load())})).then(W)}function yn(t){var e=t.views("entering"),r=t.views("exiting");if(e.length||r.length){var n=t.router.viewService;r.forEach(function(t){return n.deactivateViewConfig(t)}),e.forEach(function(t){return n.activateViewConfig(t)}),n.sync()}}function gn(t){function e(){r.transition===t&&(r.transition=null)}var r=t.router.globals;t.onSuccess({},function(){r.successfulTransitions.enqueue(t),r.$current=t.$to(),r.current=r.$current.self,kt(t.params(),r.params)},{priority:1e4}),t.promise.then(e,e)}function wn(t){var e=t.options(),r=t.router.stateService,n=t.router.urlRouter;if("url"!==e.source&&e.location&&r.$current.navigable){var i={replace:"replace"===e.location};n.push(r.$current.navigable.url,r.params,i)}n.update(!0)}function _n(a){var u=a.router,t=a.entering().filter(function(t){return!!t.$$state().lazyLoad}).map(function(t){return Rn(a,t)});return D.$q.all(t).then(function(){if("url"!==a.originalTransition().options().source){var t=a.targetState();return u.stateService.target(t.identifier(),t.params(),t.options())}var e=u.urlService,r=e.match(e.parts()),n=r&&r.rule;if(n&&"STATE"===n.type){var i=n.state,o=r.match;return u.stateService.target(i,o,a.options())}u.urlService.sync()})}var Sn=hn("onExit"),bn=hn("onRetain"),$n=hn("onEnter");function Rn(e,r){var n=r.$$state().lazyLoad,t=n._promise;if(!t){t=n._promise=D.$q.when(n(e,r)).then(function(t){t&&Array.isArray(t.states)&&t.states.forEach(function(t){return e.router.stateRegistry.register(t)});return t}).then(function(t){return delete r.lazyLoad,delete r.$$state().lazyLoad,delete n._promise,t},function(t){return delete n._promise,D.$q.reject(t)})}return t}var En=function(t,e,r,n,i,o,a,u){void 0===i&&(i=!1),void 0===o&&(o=gr.HANDLE_RESULT),void 0===a&&(a=gr.REJECT_ERROR),void 0===u&&(u=!1),this.name=t,this.hookPhase=e,this.hookOrder=r,this.criteriaMatchPath=n,this.reverseSort=i,this.getResultHandler=o,this.getErrorHandler=a,this.synchronous=u};function Cn(t){var e=t._ignoredReason();if(e){we.traceTransitionIgnored(t);var r=t.router.globals.transition;return"SameAsCurrent"===e&&r&&r.abort(),Ft.ignored().toPromise()}}function Tn(t){if(!t.valid())throw new Error(t.error().toString())}var Pn={location:!0,relative:null,inherit:!1,notify:!0,reload:!1,supercede:!0,custom:{},current:function(){return null},source:"unknown"},kn=(On.prototype.onCreate=function(t,e,r){},On.prototype.onBefore=function(t,e,r){},On.prototype.onStart=function(t,e,r){},On.prototype.onExit=function(t,e,r){},On.prototype.onRetain=function(t,e,r){},On.prototype.onEnter=function(t,e,r){},On.prototype.onFinish=function(t,e,r){},On.prototype.onSuccess=function(t,e,r){},On.prototype.onError=function(t,e,r){},On.prototype.dispose=function(t){pt(this._registeredHooks).forEach(function(e){return e.forEach(function(t){t._deregistered=!0,Z(e,t)})})},On.prototype.create=function(t,e){return new Tr(t,e,this._router)},On.prototype._defineCoreEvents=function(){var t=d.TransitionHookPhase,e=gr,r=this._criteriaPaths;this._defineEvent("onCreate",t.CREATE,0,r.to,!1,e.LOG_REJECTED_RESULT,e.THROW_ERROR,!0),this._defineEvent("onBefore",t.BEFORE,0,r.to),this._defineEvent("onStart",t.RUN,0,r.to),this._defineEvent("onExit",t.RUN,100,r.exiting,!0),this._defineEvent("onRetain",t.RUN,200,r.retained),this._defineEvent("onEnter",t.RUN,300,r.entering),this._defineEvent("onFinish",t.RUN,400,r.to),this._defineEvent("onSuccess",t.SUCCESS,0,r.to,!1,e.LOG_REJECTED_RESULT,e.LOG_ERROR,!0),this._defineEvent("onError",t.ERROR,0,r.to,!1,e.LOG_REJECTED_RESULT,e.LOG_ERROR,!0)},On.prototype._defineCorePaths=function(){var t=d.TransitionHookScope.STATE,e=d.TransitionHookScope.TRANSITION;this._definePathType("to",e),this._definePathType("from",e),this._definePathType("exiting",t),this._definePathType("retained",t),this._definePathType("entering",t)},On.prototype._defineEvent=function(t,e,r,n,i,o,a,u){void 0===i&&(i=!1),void 0===o&&(o=gr.HANDLE_RESULT),void 0===a&&(a=gr.REJECT_ERROR),void 0===u&&(u=!1);var s=new En(t,e,r,n,i,o,a,u);this._eventTypes.push(s),$r(this,this,s)},On.prototype._getEvents=function(e){return(E(e)?this._eventTypes.filter(function(t){return t.hookPhase===e}):this._eventTypes.slice()).sort(function(t,e){var r=t.hookPhase-e.hookPhase;return 0==r?t.hookOrder-e.hookOrder:r})},On.prototype._definePathType=function(t,e){this._criteriaPaths[t]={name:t,scope:e}},On.prototype._getPathTypes=function(){return this._criteriaPaths},On.prototype.getHooks=function(t){return this._registeredHooks[t]},On.prototype._registerCoreTransitionHooks=function(){var t=this._deregisterHookFns;t.addCoreResolves=function(t){return t.onCreate({},sn)}(this),t.ignored=function(t){return t.onBefore({},Cn,{priority:-9999})}(this),t.invalid=function(t){return t.onBefore({},Tn,{priority:-1e4})}(this),t.redirectTo=function(t){return t.onStart({to:function(t){return!!t.redirectTo}},fn)}(this),t.onExit=function(t){return t.onExit({exiting:function(t){return!!t.onExit}},Sn)}(this),t.onRetain=function(t){return t.onRetain({retained:function(t){return!!t.onRetain}},bn)}(this),t.onEnter=function(t){return t.onEnter({entering:function(t){return!!t.onEnter}},$n)}(this),t.eagerResolve=function(t){return t.onStart({},pn,{priority:1e3})}(this),t.lazyResolve=function(t){return t.onEnter({entering:p(!0)},vn,{priority:1e3})}(this),t.resolveAll=function(t){return t.onFinish({},dn,{priority:1e3})}(this),t.loadViews=function(t){return t.onFinish({},mn)}(this),t.activateViews=function(t){return t.onSuccess({},yn)}(this),t.updateGlobals=function(t){return t.onCreate({},gn)}(this),t.updateUrl=function(t){return t.onSuccess({},wn,{priority:9999})}(this),t.lazyLoad=function(t){return t.onBefore({entering:function(t){return!!t.lazyLoad}},_n)}(this)},On);function On(t){this._transitionCount=0,this._eventTypes=[],this._registeredHooks={},this._criteriaPaths={},this._router=t,this.$view=t.viewService,this._deregisterHookFns={},this._pluginapi=J(p(this),{},p(this),["_definePathType","_defineEvent","_getPathTypes","_getEvents","getHooks"]),this._defineCorePaths(),this._defineCoreEvents(),this._registerCoreTransitionHooks(),t.globals.successfulTransitions.onEvict(cn)}var xn=(Object.defineProperty(jn.prototype,"transition",{get:function(){return this.router.globals.transition},enumerable:!0,configurable:!0}),Object.defineProperty(jn.prototype,"params",{get:function(){return this.router.globals.params},enumerable:!0,configurable:!0}),Object.defineProperty(jn.prototype,"current",{get:function(){return this.router.globals.current},enumerable:!0,configurable:!0}),Object.defineProperty(jn.prototype,"$current",{get:function(){return this.router.globals.$current},enumerable:!0,configurable:!0}),jn.prototype.dispose=function(){this.defaultErrorHandler(W),this.invalidCallbacks=[]},jn.prototype._handleInvalidTargetState=function(t,r){function n(){return e.transitionHistory.peekTail()}var i=this,o=qe.makeTargetState(this.router.stateRegistry,t),e=this.router.globals,a=n(),u=new Dt(this.invalidCallbacks.slice()),s=new Je(t).injector(),c=function(t){if(t instanceof Ae){var e=t;return(e=i.target(e.identifier(),e.params(),e.options())).valid()?n()!==a?Ft.superseded().toPromise():i.transitionTo(e.identifier(),e.params(),e.options()):Ft.invalid(e.error()).toPromise()}};return function e(){var t=u.dequeue();return void 0===t?Ft.invalid(r.error()).toPromise():D.$q.when(t(r,o,s)).then(c).then(function(t){return t||e()})}()},jn.prototype.onInvalid=function(t){return this.invalidCallbacks.push(t),function(){Z(this.invalidCallbacks)(t)}.bind(this)},jn.prototype.reload=function(t){return this.transitionTo(this.current,this.params,{reload:!E(t)||t,inherit:!1,notify:!1})},jn.prototype.go=function(t,e,r){var n=nt(r,{relative:this.$current,inherit:!0},Pn);return this.transitionTo(t,e,n)},jn.prototype.target=function(t,e,r){if(void 0===r&&(r={}),O(r.reload)&&!r.reload.name)throw new Error("Invalid reload state object");var n=this.router.stateRegistry;if(r.reloadState=!0===r.reload?n.root():n.matcher.find(r.reload,r.relative),r.reload&&!r.reloadState)throw new Error("No such reload state '"+(k(r.reload)?r.reload:r.reload.name)+"'");return new Ae(this.router.stateRegistry,t,e,r)},jn.prototype.getCurrentPath=function(){var t=this,e=this.router.globals.successfulTransitions.peekTail();return e?e.treeChanges().to:[new He(t.router.stateRegistry.root())]},jn.prototype.transitionTo=function(t,e,r){var o=this;void 0===e&&(e={}),void 0===r&&(r={});var a=this.router,u=a.globals;function n(){return u.transition}r=nt(r,Pn),r=B(r,{current:n});var i=this.target(t,e,r),s=this.getCurrentPath();if(!i.exists())return this._handleInvalidTargetState(s,i);if(!i.valid())return Vt(i.error());if(!1===r.supercede&&n())return Ft.ignored("Another transition is in progress and supercede has been set to false in TransitionOptions for the transition. So the transition was ignored in favour of the existing one in progress.").toPromise();var c=function(i){return function(t){if(t instanceof Ft){var e=a.globals.lastStartedTransitionId<=i.$id;if(t.type===d.RejectType.IGNORED)return e&&a.urlRouter.update(),D.$q.when(u.current);var r=t.detail;if(t.type===d.RejectType.SUPERSEDED&&t.redirected&&r instanceof Ae){var n=i.redirect(r);return n.run().catch(c(n))}if(t.type===d.RejectType.ABORTED)return e&&a.urlRouter.update(),D.$q.reject(t)}return o.defaultErrorHandler()(t),D.$q.reject(t)}},f=this.router.transitionService.create(s,i),l=f.run().catch(c(f));return jt(l),B(l,{transition:f})},jn.prototype.is=function(t,e,r){r=nt(r,{relative:this.$current});var n=this.router.stateRegistry.matcher.find(t,r.relative);if(E(n)){if(this.$current!==n)return!1;if(!e)return!0;var i=n.parameters({inherit:!0,matchingKeys:e});return Te.equals(i,Te.values(i,e),this.params)}},jn.prototype.includes=function(t,e,r){r=nt(r,{relative:this.$current});var n=k(t)&&Ht.fromString(t);if(n){if(!n.matches(this.$current.name))return!1;t=this.$current.name}var i=this.router.stateRegistry.matcher.find(t,r.relative),o=this.$current.includes;if(E(i)){if(!E(o[i.name]))return!1;if(!e)return!0;var a=i.parameters({inherit:!0,matchingKeys:e});return Te.equals(a,Te.values(a,e),this.params)}},jn.prototype.href=function(t,e,r){r=nt(r,{lossy:!0,inherit:!0,absolute:!1,relative:this.$current}),e=e||{};var n=this.router.stateRegistry.matcher.find(t,r.relative);if(!E(n))return null;r.inherit&&(e=this.params.$inherit(e,this.$current,n));var i=n&&r.lossy?n.navigable:n;return i&&void 0!==i.url&&null!==i.url?this.router.urlRouter.href(i.url,e,{absolute:r.absolute}):null},jn.prototype.defaultErrorHandler=function(t){return this._defaultErrorHandler=t||this._defaultErrorHandler},jn.prototype.get=function(t,e){var r=this.router.stateRegistry;return 0===arguments.length?r.get():r.get(t,e||this.$current)},jn.prototype.lazyLoad=function(t,e){var r=this.get(t);if(!r||!r.lazyLoad)throw new Error("Can not lazy load "+t);var n=this.getCurrentPath(),i=qe.makeTargetState(this.router.stateRegistry,n);return Rn(e=e||this.router.transitionService.create(n,i),r)},jn);function jn(t){this.router=t,this.invalidCallbacks=[],this._defaultErrorHandler=function(t){t instanceof Error&&t.stack?(console.error(t),console.error(t.stack)):t instanceof Ft?(console.error(t.toString()),t.detail&&t.detail.stack&&console.error(t.detail.stack)):console.error(t)};var e=Object.keys(jn.prototype).filter(l(K(["current","$current","params","transition"])));J(p(jn.prototype),this,p(this),e)}function Vn(t,e){var r=e[0],n=e[1];return t.hasOwnProperty(r)?x(t[r])?t[r].push(n):t[r]=[t[r],n]:t[r]=n,t}function Hn(t){return t.split("&").filter(z).map(re).reduce(Vn,{})}var In={when:function(r){return new Promise(function(t,e){return t(r)})},reject:function(r){return new Promise(function(t,e){e(r)})},defer:function(){var r={};return r.promise=new Promise(function(t,e){r.resolve=t,r.reject=e}),r},all:function(t){if(x(t))return Promise.all(t);if(O(t)){var e=Object.keys(t).map(function(e){return t[e].then(function(t){return{key:e,val:t}})});return In.all(e).then(function(t){return t.reduce(function(t,e){return t[e.key]=e.val,t},{})})}}},An={},Dn=/((\/\/.*$)|(\/\*[\s\S]*?\*\/))/gm,qn=/([^\s,]+)/g,Un={get:function(t){return An[t]},has:function(t){return null!=Un.get(t)},invoke:function(t,e,r){var n=B({},An,r||{}),i=Un.annotate(t),o=bt(function(t){return n.hasOwnProperty(t)},function(t){return"DI can't find injectable: '"+t+"'"}),a=i.filter(o).map(function(t){return n[t]});return T(t)?t.apply(e,a):t.slice(-1)[0].apply(e,a)},annotate:function(t){if(!H(t))throw new Error("Not an injectable function: "+t);if(t&&t.$inject)return t.$inject;if(x(t))return t.slice(0,-1);var e=t.toString().replace(Dn,"");return e.slice(e.indexOf("(")+1,e.indexOf(")")).match(qn)||[]}};function Fn(t){function e(t){return t||""}var r=te(t).map(e),n=r[0],i=r[1],o=ee(n).map(e);return{path:o[0],search:o[1],hash:i,url:t}}function Nn(t){var e=t.path(),r=t.search(),n=t.hash(),i=Object.keys(r).map(function(e){var t=r[e];return(x(t)?t:[t]).map(function(t){return e+"="+t})}).reduce(mt,[]).join("&");return e+(i?"?"+i:"")+(n?"#"+n:"")}function Ln(n,i,o,a){return function(t){var e=t.locationService=new o(t),r=t.locationConfig=new a(t,i);return{name:n,service:e,configuration:r,dispose:function(t){t.dispose(e),t.dispose(r)}}}}var Mn=(Bn.prototype.url=function(e,t){return void 0===t&&(t=!0),E(e)&&e!==this._get()&&(this._set(null,null,e,t),this.fireAfterUpdate&&this._listeners.forEach(function(t){return t({url:e})})),Nn(this)},Bn.prototype.onChange=function(t){var e=this;return this._listeners.push(t),function(){return Z(e._listeners,t)}},Bn.prototype.dispose=function(t){rt(this._listeners)},Bn);function Bn(t,e){var r=this;this.fireAfterUpdate=e,this._listeners=[],this._listener=function(e){return r._listeners.forEach(function(t){return t(e)})},this.hash=function(){return Fn(r._get()).hash},this.path=function(){return Fn(r._get()).path},this.search=function(){return Hn(Fn(r._get()).search)},this._location=U.location,this._history=U.history}var Gn,zn,Wn=((Gn=function(t,e){return(Gn=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var r in e)e.hasOwnProperty(r)&&(t[r]=e[r])})(t,e)},function(t,e){function r(){this.constructor=t}Gn(t,e),t.prototype=null===e?Object.create(e):(r.prototype=e.prototype,new r)})(Jn,zn=Mn),Jn.prototype._get=function(){return Zt(this._location.hash)},Jn.prototype._set=function(t,e,r,n){this._location.hash=r},Jn.prototype.dispose=function(t){zn.prototype.dispose.call(this,t),U.removeEventListener("hashchange",this._listener)},Jn);function Jn(t){var e=zn.call(this,t,!1)||this;return U.addEventListener("hashchange",e._listener,!1),e}var Qn,Kn,Yn=((Qn=function(t,e){return(Qn=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var r in e)e.hasOwnProperty(r)&&(t[r]=e[r])})(t,e)},function(t,e){function r(){this.constructor=t}Qn(t,e),t.prototype=null===e?Object.create(e):(r.prototype=e.prototype,new r)})(Zn,Kn=Mn),Zn.prototype._get=function(){return this._url},Zn.prototype._set=function(t,e,r,n){this._url=r},Zn);function Zn(t){return Kn.call(this,t,!0)||this}var Xn,ti,ei=((Xn=function(t,e){return(Xn=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var r in e)e.hasOwnProperty(r)&&(t[r]=e[r])})(t,e)},function(t,e){function r(){this.constructor=t}Xn(t,e),t.prototype=null===e?Object.create(e):(r.prototype=e.prototype,new r)})(ri,ti=Mn),ri.prototype._getBasePrefix=function(){return Yt(this._config.baseHref())},ri.prototype._get=function(){var t=this._location,e=t.pathname,r=t.hash,n=t.search;n=ee(n)[1],r=te(r)[1];var i=this._getBasePrefix(),o=e===this._config.baseHref(),a=e.substr(0,i.length)===i;return(e=o?"/":a?e.substring(i.length):e)+(n?"?"+n:"")+(r?"#"+r:"")},ri.prototype._set=function(t,e,r,n){var i=this._getBasePrefix(),o=r&&"/"!==r[0]?"/":"",a=""===r||"/"===r?this._config.baseHref():i+o+r;n?this._history.replaceState(t,e,a):this._history.pushState(t,e,a)},ri.prototype.dispose=function(t){ti.prototype.dispose.call(this,t),U.removeEventListener("popstate",this._listener)},ri);function ri(t){var e=ti.call(this,t,!0)||this;return e._config=t.urlService.config,U.addEventListener("popstate",e._listener,!1),e}function ni(){var e=this;this.dispose=W,this._baseHref="",this._port=80,this._protocol="http",this._host="localhost",this._hashPrefix="",this.port=function(){return e._port},this.protocol=function(){return e._protocol},this.host=function(){return e._host},this.baseHref=function(){return e._baseHref},this.html5Mode=function(){return!1},this.hashPrefix=function(t){return E(t)?e._hashPrefix=t:e._hashPrefix}}var ii=(oi.prototype.port=function(){return location.port?Number(location.port):"https"===this.protocol()?443:80},oi.prototype.protocol=function(){return location.protocol.replace(/:/g,"")},oi.prototype.host=function(){return location.hostname},oi.prototype.html5Mode=function(){return this._isHtml5},oi.prototype.hashPrefix=function(t){return E(t)?this._hashPrefix=t:this._hashPrefix},oi.prototype.baseHref=function(t){return E(t)&&(this._baseHref=t),b(this._baseHref)&&(this._baseHref=this.getBaseHref()),this._baseHref},oi.prototype.getBaseHref=function(){var t=document.getElementsByTagName("base")[0];return t&&t.href?t.href.replace(/^([^/:]*:)?\/\/[^/]*/,""):this._isHtml5?"/":location.pathname||"/"},oi.prototype.dispose=function(){},oi);function oi(t,e){void 0===e&&(e=!1),this._isHtml5=e,this._baseHref=void 0,this._hashPrefix=""}function ai(t){return D.$injector=Un,{name:"vanilla.services",$q:D.$q=In,$injector:Un,dispose:function(){return null}}}var ui=Ln("vanilla.hashBangLocation",!1,Wn,ii),si=Ln("vanilla.pushStateLocation",!0,ei,ii),ci=Ln("vanilla.memoryLocation",!1,Yn,ni),fi=(li.prototype.dispose=function(t){},li);function li(){}var hi=Object.freeze({__proto__:null,root:U,fromJson:N,toJson:L,forEach:M,extend:B,equals:G,identity:z,noop:W,createProxyFunctions:J,inherit:Q,inArray:K,_inArray:Y,removeFrom:Z,_removeFrom:X,pushTo:tt,_pushTo:et,deregAll:rt,defaults:nt,mergeR:it,ancestors:ot,pick:at,omit:ut,pluck:st,filter:ct,find:ft,mapObj:lt,map:ht,values:pt,allTrueR:vt,anyTrueR:dt,unnestR:mt,flattenR:yt,pushR:gt,uniqR:wt,unnest:_t,flatten:St,assertPredicate:bt,assertMap:$t,assertFn:Rt,pairs:Et,arrayTuples:Ct,applyPairs:Tt,tail:Pt,copy:kt,_extend:Ot,silenceUncaughtInPromise:jt,silentRejection:Vt,makeStub:I,services:D,Glob:Ht,curry:s,compose:r,pipe:c,prop:m,propEq:y,parse:R,not:l,and:i,or:o,all:u,any:f,is:h,eq:a,val:p,invoke:v,pattern:g,isUndefined:b,isDefined:E,isNull:_,isNullOrUndefined:C,isFunction:T,isNumber:P,isString:k,isObject:O,isArray:x,isDate:j,isRegExp:V,isInjectable:H,isPromise:A,Queue:Dt,maxLength:Lt,padString:Mt,kebobString:Bt,functionToString:Gt,fnToString:zt,stringify:Qt,beforeAfterSubstr:Kt,hostRegex:Xt,stripLastPathElement:Yt,splitHash:te,splitQuery:ee,splitEqual:re,trimHashVal:Zt,splitOnDelim:ne,joinNeighborsR:ie,get Category(){return d.Category},Trace:ye,trace:we,get DefType(){return d.DefType},Param:Te,ParamTypes:ke,StateParams:je,ParamType:_e,PathNode:He,PathUtils:qe,resolvePolicies:Fe,defaultResolvePolicy:Ne,Resolvable:Le,NATIVE_INJECTOR_TOKEN:We,ResolveContext:Je,resolvablesBuilder:ir,StateBuilder:or,StateObject:ur,StateMatcher:cr,StateQueueManager:lr,StateRegistry:dr,StateService:xn,TargetState:Ae,get TransitionHookPhase(){return d.TransitionHookPhase},get TransitionHookScope(){return d.TransitionHookScope},HookBuilder:Rr,matchState:_r,RegisteredHook:Sr,makeEvent:$r,get RejectType(){return d.RejectType},Rejection:Ft,Transition:Tr,TransitionHook:gr,TransitionEventType:En,defaultTransOpts:Pn,TransitionService:kn,UrlRules:Kr,UrlConfig:Zr,UrlMatcher:jr,ParamFactory:Ir,UrlMatcherFactory:Dr,UrlRouter:Lr,UrlRuleFactory:Ur,BaseUrlRule:Nr,UrlService:tn,ViewService:Br,UIRouterGlobals:zr,UIRouter:an,$q:In,$injector:Un,BaseLocationServices:Mn,HashLocationService:Wn,MemoryLocationService:Yn,PushStateLocationService:ei,MemoryLocationConfig:ni,BrowserLocationConfig:ii,keyValsToObjectR:Vn,getParams:Hn,parseUrl:Fn,buildUrl:Nn,locationPluginFactory:Ln,servicesPlugin:ai,hashLocationPlugin:ui,pushStateLocationPlugin:si,memoryLocationPlugin:ci,UIRouterPluginBase:fi});function pi(){var r=null;return function(t,e){return r=r||D.$injector.get("$templateFactory"),[new yi(t,e,r)]}}var vi=function(t,r){return t.reduce(function(t,e){return t||E(r[e])},!1)};function di(n){if(!n.parent)return{};var i=["component","bindings","componentProvider"],o=["templateProvider","templateUrl","template","notify","async"].concat(["controller","controllerProvider","controllerAs","resolveAs"]),t=i.concat(o);if(E(n.views)&&vi(t,n))throw new Error("State '"+n.name+"' has a 'views' object. It cannot also have \"view properties\" at the state level.  Move the following properties into a view (in the 'views' object):  "+t.filter(function(t){return E(n[t])}).join(", "));var a={},e=n.views||{$default:at(n,t)};return M(e,function(t,e){if(e=e||"$default",k(t)&&(t={component:t}),t=B({},t),vi(i,t)&&vi(o,t))throw new Error("Cannot combine: "+i.join("|")+" with: "+o.join("|")+" in stateview: '"+e+"@"+n.name+"'");t.resolveAs=t.resolveAs||"$resolve",t.$type="ng1",t.$context=n,t.$name=e;var r=Br.normalizeUIViewTarget(t.$context,t.$name);t.$uiViewName=r.uiViewName,t.$uiViewContextAnchor=r.uiViewContextAnchor,a[e]=t}),a}var mi=0,yi=(gi.prototype.load=function(){var e=this,t=D.$q,r=new Je(this.path),n=this.path.reduce(function(t,e){return B(t,e.paramValues)},{}),i={template:t.when(this.factory.fromConfig(this.viewDecl,n,r)),controller:t.when(this.getController(r))};return t.all(i).then(function(t){return we.traceViewServiceEvent("Loaded",e),e.controller=t.controller,B(e,t.template),e})},gi.prototype.getController=function(t){var e=this.viewDecl.controllerProvider;if(!H(e))return this.viewDecl.controller;var r=D.$injector.annotate(e),n=x(e)?Pt(e):e;return new Le("",n,r).get(t)},gi);function gi(t,e,r){var n=this;this.path=t,this.viewDecl=e,this.factory=r,this.$id=mi++,this.loaded=!1,this.getTemplate=function(t,e){return n.component?n.factory.makeComponentTemplate(t,e,n.component,n.viewDecl.bindings):n.template}}var wi=(_i.prototype.useHttpService=function(t){this._useHttp=t},_i.prototype.fromConfig=function(t,e,r){function n(t){return D.$q.when(t).then(function(t){return{template:t}})}function i(t){return D.$q.when(t).then(function(t){return{component:t}})}return E(t.template)?n(this.fromString(t.template,e)):E(t.templateUrl)?n(this.fromUrl(t.templateUrl,e)):E(t.templateProvider)?n(this.fromProvider(t.templateProvider,e,r)):E(t.component)?i(t.component):E(t.componentProvider)?i(this.fromComponentProvider(t.componentProvider,e,r)):n("<ui-view></ui-view>")},_i.prototype.fromString=function(t,e){return T(t)?t(e):t},_i.prototype.fromUrl=function(t,e){return T(t)&&(t=t(e)),null==t?null:this._useHttp?this.$http.get(t,{cache:this.$templateCache,headers:{Accept:"text/html"}}).then(function(t){return t.data}):this.$templateRequest(t)},_i.prototype.fromProvider=function(t,e,r){var n=D.$injector.annotate(t),i=x(t)?Pt(t):t;return new Le("",i,n).get(r)},_i.prototype.fromComponentProvider=function(t,e,r){var n=D.$injector.annotate(t),i=x(t)?Pt(t):t;return new Le("",i,n).get(r)},_i.prototype.makeComponentTemplate=function(s,c,t,f){function l(t){var e=Bt(t);return/^(x|data)-/.exec(e)?"x-"+e:e}f=f||{};var h=3<=$.version.minor?"::":"",e=function(t){var e=D.$injector.get(t+"Directive");if(!e||!e.length)throw new Error("Unable to find component named '"+t+"'");return e.map(Si).reduce(mt,[])}(t).map(function(t){var e=t.name,r=t.type,n=l(e);if(s.attr(n)&&!f[e])return n+"='"+s.attr(n)+"'";var i=f[e]||e;if("@"===r)return n+"='{{"+h+"$resolve."+i+"}}'";if("&"!==r)return n+"='"+h+"$resolve."+i+"'";var o=c.getResolvable(i),a=o&&o.data,u=a&&D.$injector.annotate(a)||[];return n+"='$resolve."+i+(x(a)?"["+(a.length-1)+"]":"")+"("+u.join(",")+")'"}).join(" "),r=l(t);return"<"+r+" "+e+"></"+r+">"},_i);function _i(){var n=this;this._useHttp=$.version.minor<3,this.$get=["$http","$templateCache","$injector",function(t,e,r){return n.$templateRequest=r.has&&r.has("$templateRequest")&&r.get("$templateRequest"),n.$http=t,n.$templateCache=e,n}]}var Si=function(t){return O(t.bindToController)?bi(t.bindToController):bi(t.scope)},bi=function(e){return Object.keys(e||{}).map(function(t){return[t,/^([=<@&])[?]?(.*)/.exec(e[t])]}).filter(function(t){return E(t)&&x(t[1])}).map(function(t){return{name:t[1][2]||t[0],type:t[1][1]}})},$i=(Ri.prototype.decorator=function(t,e){return this.stateRegistry.decorator(t,e)||this},Ri.prototype.state=function(t,e){return O(t)?e=t:e.name=t,this.stateRegistry.register(e),this},Ri.prototype.onInvalid=function(t){return this.stateService.onInvalid(t)},Ri);function Ri(t,e){this.stateRegistry=t,this.stateService=e,J(p(Ri.prototype),this,p(this))}function Ei(r){return function(t,e){var i=t[r],o="onExit"===r?"from":"to";return i?function(t,e){var r=new Je(t.treeChanges(o)).subContext(e.$$state()),n=B(Bi(r),{$state$:e,$transition$:t});return D.$injector.invoke(i,this,n)}:void 0}}var Ci=(Ti.monkeyPatchPathParameterType=function(t){var e=t.urlMatcherFactory.type("path");e.encode=function(t){return null!=t?t.toString().replace(/(~|\/)/g,function(t){return{"~":"~~","/":"~2F"}[t]}):t},e.decode=function(t){return null!=t?t.toString().replace(/(~~|~2F)/g,function(t){return{"~~":"~","~2F":"/"}[t]}):t}},Ti.prototype.dispose=function(){},Ti.prototype.onChange=function(t){var e=this;return this._urlListeners.push(t),function(){return Z(e._urlListeners)(t)}},Ti.prototype.html5Mode=function(){var t=this.$locationProvider.html5Mode();return(t=O(t)?t.enabled:t)&&this.$sniffer.history},Ti.prototype.baseHref=function(){return this._baseHref||(this._baseHref=this.$browser.baseHref()||this.$window.location.pathname)},Ti.prototype.url=function(t,e,r){return void 0===e&&(e=!1),E(t)&&this.$location.url(t),e&&this.$location.replace(),r&&this.$location.state(r),this.$location.url()},Ti.prototype._runtimeServices=function(t,e,r,n,i){var o=this;this.$location=e,this.$sniffer=r,this.$browser=n,this.$window=i,t.$on("$locationChangeSuccess",function(e){return o._urlListeners.forEach(function(t){return t(e)})});var a=p(e);J(a,this,a,["replace","path","search","hash"]),J(a,this,a,["port","protocol","host"])},Ti);function Ti(t){this._urlListeners=[],this.$locationProvider=t;var e=p(t);J(e,this,e,["hashPrefix"])}var Pi=(ki.injectableHandler=function(e,r){return function(t){return D.$injector.invoke(r,null,{$match:t,$stateParams:e.globals.params})}},ki.prototype.$get=function(){var t=this.router.urlService;return this.router.urlRouter.update(!0),t.interceptDeferred||t.listen(),this.router.urlRouter},ki.prototype.rule=function(t){var e=this;if(!T(t))throw new Error("'rule' must be a function");var r=new Nr(function(){return t(D.$injector,e.router.locationService)},z);return this.router.urlService.rules.rule(r),this},ki.prototype.otherwise=function(t){var e=this,r=this.router.urlService.rules;if(k(t))r.otherwise(t);else{if(!T(t))throw new Error("'rule' must be a string or function");r.otherwise(function(){return t(D.$injector,e.router.locationService)})}return this},ki.prototype.when=function(t,e){return(x(e)||T(e))&&(e=ki.injectableHandler(this.router,e)),this.router.urlService.rules.when(t,e),this},ki.prototype.deferIntercept=function(t){this.router.urlService.deferIntercept(t)},ki);function ki(t){this.router=t}$.module("ui.router.angular1",[]);var Oi=$.module("ui.router.init",["ng"]),xi=$.module("ui.router.util",["ui.router.init"]),ji=$.module("ui.router.router",["ui.router.util"]),Vi=$.module("ui.router.state",["ui.router.router","ui.router.util","ui.router.angular1"]),Hi=$.module("ui.router",["ui.router.init","ui.router.state","ui.router.angular1"]),Ii=($.module("ui.router.compat",["ui.router"]),null);function Ai(t){(Ii=this.router=new an).stateProvider=new $i(Ii.stateRegistry,Ii.stateService),Ii.stateRegistry.decorator("views",di),Ii.stateRegistry.decorator("onExit",Ei("onExit")),Ii.stateRegistry.decorator("onRetain",Ei("onRetain")),Ii.stateRegistry.decorator("onEnter",Ei("onEnter")),Ii.viewService._pluginapi._viewConfigFactory("ng1",pi());var u=Ii.locationService=Ii.locationConfig=new Ci(t);function e(t,e,r,n,i,o,a){return u._runtimeServices(i,t,n,e,r),delete Ii.router,delete Ii.$get,Ii}return Ci.monkeyPatchPathParameterType(Ii),((Ii.router=Ii).$get=e).$inject=["$location","$browser","$window","$sniffer","$rootScope","$http","$templateCache"],Ii}Ai.$inject=["$locationProvider"];function Di(r){return["$uiRouterProvider",function(t){var e=t.router[r];return e.$get=function(){return e},e}]}function qi(e,t,r){if(D.$injector=e,D.$q=t,!e.hasOwnProperty("strictDi"))try{e.invoke(function(t){})}catch(t){e.strictDi=!!/strict mode/.exec(t&&t.toString())}r.stateRegistry.get().map(function(t){return t.$$state().resolvables}).reduce(mt,[]).filter(function(t){return"deferred"===t.deps}).forEach(function(t){return t.deps=e.annotate(t.resolveFn,e.strictDi)})}qi.$inject=["$injector","$q","$uiRouter"];function Ui(t){t.$watch(function(){we.approximateDigests++})}Ui.$inject=["$rootScope"],Oi.provider("$uiRouter",Ai),ji.provider("$urlRouter",["$uiRouterProvider",function(t){return t.urlRouterProvider=new Pi(t)}]),xi.provider("$urlService",Di("urlService")),xi.provider("$urlMatcherFactory",["$uiRouterProvider",function(){return Ii.urlMatcherFactory}]),xi.provider("$templateFactory",function(){return new wi}),Vi.provider("$stateRegistry",Di("stateRegistry")),Vi.provider("$uiRouterGlobals",Di("globals")),Vi.provider("$transitions",Di("transitionService")),Vi.provider("$state",["$uiRouterProvider",function(){return B(Ii.stateProvider,{$get:function(){return Ii.stateService}})}]),Vi.factory("$stateParams",["$uiRouter",function(t){return t.globals.params}]),Hi.factory("$view",function(){return Ii.viewService}),Hi.service("$trace",function(){return we}),Hi.run(Ui),xi.run(["$urlMatcherFactory",function(t){}]),Vi.run(["$state",function(t){}]),ji.run(["$urlRouter",function(t){}]),Oi.run(qi);var Fi,Ni,Li,Mi,Bi=function(r){return r.getTokens().filter(k).map(function(t){var e=r.getResolvable(t);return[t,"NOWAIT"===r.getPolicy(e).async?e.promise:e.data]}).reduce(Tt,{})};function Gi(t){var e,r=t.match(/^\s*({[^}]*})\s*$/);if(r&&(t="("+r[1]+")"),!(e=t.replace(/\n/g," ").match(/^\s*([^(]*?)\s*(\((.*)\))?\s*$/))||4!==e.length)throw new Error("Invalid state ref '"+t+"'");return{state:e[1]||null,paramExpr:e[3]||null}}function zi(t){var e=t.parent().inheritedData("$uiView"),r=R("$cfg.path")(e);return r?Pt(r).state.name:void 0}function Wi(t,e,r){var n=r.uiState||t.current.name,i=B(function(t,e){return{relative:zi(t)||e.$current,inherit:!0,source:"sref"}}(e,t),r.uiStateOpts||{}),o=t.href(n,r.uiStateParams,i);return{uiState:n,uiStateParams:r.uiStateParams,uiStateOpts:i,href:o}}function Ji(t){var e="[object SVGAnimatedString]"===Object.prototype.toString.call(t.prop("href")),r="FORM"===t[0].nodeName;return{attr:r?"action":e?"xlink:href":"href",isAnchor:"A"===t.prop("tagName").toUpperCase(),clickable:!r}}function Qi(o,a,u,s,c){return function(t){var e=t.which||t.button,r=c();if(!(1<e||t.ctrlKey||t.metaKey||t.shiftKey||o.attr("target"))){var n=u(function(){o.attr("disabled")||a.go(r.uiState,r.uiStateParams,r.uiStateOpts)});t.preventDefault();var i=s.isAnchor&&!r.href?1:0;t.preventDefault=function(){i--<=0&&u.cancel(n)}}}}function Ki(i,t,o,e){var a;e&&(a=e.events),x(a)||(a=["click"]);for(var r=i.on?"on":"bind",n=0,u=a;n<u.length;n++){var s=u[n];i[r](s,o)}t.$on("$destroy",function(){for(var t=i.off?"off":"unbind",e=0,r=a;e<r.length;e++){var n=r[e];i[t](n,o)}})}function Yi(n){function t(t,e,r){return n.is(t,e,r)}return t.$stateful=!0,t}function Zi(n){function t(t,e,r){return n.includes(t,e,r)}return t.$stateful=!0,t}function Xi(d,m,y,t,g,e){var w=R("viewDecl.controllerAs"),_=R("viewDecl.resolveAs");return{restrict:"ECA",priority:-400,compile:function(t){var v=t.html();return t.empty(),function(e,r){var t=r.data("$uiView");if(!t)return r.html(v),void d(r.contents())(e);var n=t.$cfg||{viewDecl:{},getTemplate:W},i=n.path&&new Je(n.path);r.html(n.getTemplate(r,i)||v),we.traceUIViewFill(t.$uiView,r.html());var o=d(r.contents()),a=n.controller,u=w(n),s=_(n),c=i&&Bi(i);if(e[s]=c,a){var f=m(a,B({},c,{$scope:e,$element:r}));u&&(e[u]=f,e[u][s]=c),r.data("$ngControllerController",f),r.children().data("$ngControllerController",f),ro(g,y,f,e,n)}if(k(n.component))var l=Bt(n.component),h=new RegExp("^(x-|data-)?"+l+"$","i"),p=e.$watch(function(){var t=[].slice.call(r[0].children).filter(function(t){return t&&t.tagName&&h.exec(t.tagName)});return t&&$.element(t).data("$"+n.component+"Controller")},function(t){t&&(ro(g,y,t,e,n),p())});o(e)}}}}Fi=["$uiRouter","$timeout",function(h,p){var v=h.stateService;return{restrict:"A",require:["?^uiSrefActive","?^uiSrefActiveEq"],link:function(t,e,r,n){function i(){return Wi(v,e,c)}var o,a=Ji(e),u=n[1]||n[0],s=null,c={},f=Gi(r.uiSref);function l(){var t=i();s&&s(),u&&(s=u.$$addStateInfo(t.uiState,t.uiStateParams)),null!=t.href&&r.$set(a.attr,t.href)}c.uiState=f.state,c.uiStateOpts=r.uiSrefOpts?t.$eval(r.uiSrefOpts):{},f.paramExpr&&(t.$watch(f.paramExpr,function(t){c.uiStateParams=B({},t),l()},!0),c.uiStateParams=B({},t.$eval(f.paramExpr))),l(),t.$on("$destroy",h.stateRegistry.onStatesChanged(l)),t.$on("$destroy",h.transitionService.onSuccess({},l)),a.clickable&&(o=Qi(e,v,p,a,i),Ki(e,t,o,c.uiStateOpts))}}}],Ni=["$uiRouter","$timeout",function(p,v){var d=p.stateService;return{restrict:"A",require:["?^uiSrefActive","?^uiSrefActiveEq"],link:function(r,t,n,e){function i(){return Wi(d,t,c)}var o,a=Ji(t),u=e[1]||e[0],s=null,c={},f=["uiState","uiStateParams","uiStateOpts"],l=f.reduce(function(t,e){return t[e]=W,t},{});function h(){var t=i();s&&s(),u&&(s=u.$$addStateInfo(t.uiState,t.uiStateParams)),null!=t.href&&n.$set(a.attr,t.href)}f.forEach(function(e){c[e]=n[e]?r.$eval(n[e]):null,n.$observe(e,function(t){l[e](),l[e]=r.$watch(t,function(t){c[e]=t,h()},!0)})}),h(),r.$on("$destroy",p.stateRegistry.onStatesChanged(h)),r.$on("$destroy",p.transitionService.onSuccess({},h)),a.clickable&&(o=Qi(t,d,v,a,i),Ki(t,r,o,c.uiStateOpts))}}}],Li=["$state","$stateParams","$interpolate","$uiRouter",function(v,t,d,m){return{restrict:"A",controller:["$scope","$element","$attrs",function(u,s,t){var c,n,e,r,i,f=[];c=d(t.uiSrefActiveEq||"",!1)(u);try{n=u.$eval(t.uiSrefActive)}catch(t){}function o(t){t.promise.then(p,W)}function a(){l(n)}function l(t){O(t)&&(f=[],M(t,function(t,e){function r(t,e){var r=Gi(t);h(r.state,u.$eval(r.paramExpr),e)}k(t)?r(t,e):x(t)&&M(t,function(t){r(t,e)})}))}function h(t,e,r){var n={state:v.get(t,zi(s))||{name:t},params:e,activeClass:r};return f.push(n),function(){Z(f)(n)}}function p(){function e(t){return t.split(/\s/).filter(z)}function t(t){return t.map(function(t){return t.activeClass}).map(e).reduce(mt,[])}var r=t(f).concat(e(c)).reduce(wt,[]),n=t(f.filter(function(t){return v.includes(t.state.name,t.params)})),i=!!f.filter(function(t){return v.is(t.state.name,t.params)}).length?e(c):[],o=n.concat(i).reduce(wt,[]),a=r.filter(function(t){return!K(o,t)});u.$evalAsync(function(){o.forEach(function(t){return s.addClass(t)}),a.forEach(function(t){return s.removeClass(t)})})}l(n=n||d(t.uiSrefActive||"",!1)(u)),this.$$addStateInfo=function(t,e){if(!(O(n)&&0<f.length)){var r=h(t,e,n);return p(),r}},u.$on("$destroy",(e=m.stateRegistry.onStatesChanged(a),r=m.transitionService.onStart({},o),i=u.$on("$stateChangeSuccess",p),function(){e(),r(),i()})),m.globals.transition&&o(m.globals.transition),p()}]}}],$.module("ui.router.state").directive("uiSref",Fi).directive("uiSrefActive",Li).directive("uiSrefActiveEq",Li).directive("uiState",Ni),Yi.$inject=["$state"],Zi.$inject=["$state"],$.module("ui.router.state").filter("isState",Yi).filter("includedByState",Zi),Mi=["$view","$animate","$uiViewScroll","$interpolate","$q",function(i,o,g,w,_){var S={$cfg:{viewDecl:{$context:i._pluginapi._rootViewContext()}},$uiView:{}},b={count:0,restrict:"ECA",terminal:!0,priority:400,transclude:"element",compile:function(t,e,y){return function(a,u,t){var s,c,f,l,e,h=t.onload||"",p=t.autoscroll,v={enter:function(t,e,r){2<$.version.minor?o.enter(t,null,e).then(r):o.enter(t,null,e,r)},leave:function(t,e){2<$.version.minor?o.leave(t).then(e):o.leave(t,e)}},r=u.inheritedData("$uiView")||S,d=w(t.uiView||t.name||"")(a)||"$default",m={$type:"ng1",id:b.count++,name:d,fqn:r.$uiView.fqn?r.$uiView.fqn+"."+d:d,config:null,configUpdated:function(t){if(t&&!(t instanceof yi))return;if(function(t,e){return t===e}(l,t))return;we.traceUIViewConfigUpdated(m,t&&t.viewDecl&&t.viewDecl.$context),n(l=t)},get creationContext(){var t=R("$cfg.viewDecl.$context")(r),e=R("$uiView.creationContext")(r);return t||e}};function n(t){var e=a.$new(),r=_.defer(),n=_.defer(),i={$cfg:t,$uiView:m},o={$animEnter:r.promise,$animLeave:n.promise,$$animLeave:n};e.$emit("$viewContentLoading",d),c=y(e,function(t){t.data("$uiViewAnim",o),t.data("$uiView",i),v.enter(t,u,function(){r.resolve(),f&&f.$emit("$viewContentAnimationEnded"),(E(p)&&!p||a.$eval(p))&&g(t)}),function(){if(s&&(we.traceUIViewEvent("Removing (previous) el",s.data("$uiView")),s.remove(),s=null),f&&(we.traceUIViewEvent("Destroying scope",m),f.$destroy(),f=null),c){var t=c.data("$uiViewAnim");we.traceUIViewEvent("Animate out",t),v.leave(c,function(){t.$$animLeave.resolve(),s=null}),s=c,c=null}}()}),(f=e).$emit("$viewContentLoaded",t||l),f.$eval(h)}we.traceUIViewEvent("Linking",m),u.data("$uiView",{$uiView:m}),n(),e=i.registerUIView(m),a.$on("$destroy",function(){we.traceUIViewEvent("Destroying/Unregistering",m),e()})}}};return b}],Xi.$inject=["$compile","$controller","$transitions","$view","$q","$timeout"];var to="function"==typeof $.module("ui.router").component,eo=0;function ro(n,t,c,e,r){!T(c.$onInit)||(r.viewDecl.component||r.viewDecl.componentProvider)&&to||c.$onInit();var f=Pt(r.path).state.self,i={bind:c};if(T(c.uiOnParamsChanged)){var l=new Je(r.path).getResolvable("$transition$").data;e.$on("$destroy",t.onSuccess({},function(t){if(t!==l&&-1===t.exiting().indexOf(f)){var r=t.params("to"),n=t.params("from"),e=function(t){return t.paramSchema},i=t.treeChanges("to").map(e).reduce(mt,[]),o=t.treeChanges("from").map(e).reduce(mt,[]),a=i.filter(function(t){var e=o.indexOf(t);return-1===e||!o[e].type.equals(r[t.id],n[t.id])});if(a.length){var u=a.map(function(t){return t.id}),s=ct(r,function(t,e){return-1!==u.indexOf(e)});c.uiOnParamsChanged(s,t)}}},i))}if(T(c.uiCanExit)){var o=eo++,a="_uiCanExitIds",u=function(t){return!!t&&(t[a]&&!0===t[a][o]||u(t.redirectedFrom()))},s={exiting:f.name};e.$on("$destroy",t.onBefore(s,function(t){var e,r=t[a]=t[a]||{};return u(t)||(e=n.when(c.uiCanExit(t))).then(function(t){return r[o]=!1!==t}),e},i))}}$.module("ui.router.state").directive("uiView",Mi),$.module("ui.router.state").directive("uiView",Xi),$.module("ui.router.state").provider("$uiViewScroll",function(){var r=!1;this.useAnchorScroll=function(){r=!0},this.$get=["$anchorScroll","$timeout",function(t,e){return r?t:function(t){return e(function(){t[0].scrollIntoView()},0,!1)}}]});d.$injector=Un,d.$q=In,d.BaseLocationServices=Mn,d.BaseUrlRule=Nr,d.BrowserLocationConfig=ii,d.Glob=Ht,d.HashLocationService=Wn,d.HookBuilder=Rr,d.MemoryLocationConfig=ni,d.MemoryLocationService=Yn,d.NATIVE_INJECTOR_TOKEN=We,d.Ng1ViewConfig=yi,d.Param=Te,d.ParamFactory=Ir,d.ParamType=_e,d.ParamTypes=ke,d.PathNode=He,d.PathUtils=qe,d.PushStateLocationService=ei,d.Queue=Dt,d.RegisteredHook=Sr,d.Rejection=Ft,d.Resolvable=Le,d.ResolveContext=Je,d.StateBuilder=or,d.StateMatcher=cr,d.StateObject=ur,d.StateParams=je,d.StateProvider=$i,d.StateQueueManager=lr,d.StateRegistry=dr,d.StateService=xn,d.TargetState=Ae,d.Trace=ye,d.Transition=Tr,d.TransitionEventType=En,d.TransitionHook=gr,d.TransitionService=kn,d.UIRouter=an,d.UIRouterGlobals=zr,d.UIRouterPluginBase=fi,d.UrlConfig=Zr,d.UrlMatcher=jr,d.UrlMatcherFactory=Dr,d.UrlRouter=Lr,d.UrlRouterProvider=Pi,d.UrlRuleFactory=Ur,d.UrlRules=Kr,d.UrlService=tn,d.ViewService=Br,d._extend=Ot,d._inArray=Y,d._pushTo=et,d._removeFrom=X,d.all=u,d.allTrueR=vt,d.ancestors=ot,d.and=i,d.any=f,d.anyTrueR=dt,d.applyPairs=Tt,d.arrayTuples=Ct,d.assertFn=Rt,d.assertMap=$t,d.assertPredicate=bt,d.beforeAfterSubstr=Kt,d.buildUrl=Nn,d.compose=r,d.copy=kt,d.core=hi,d.createProxyFunctions=J,d.curry=s,d.default="ui.router",d.defaultResolvePolicy=Ne,d.defaultTransOpts=Pn,d.defaults=nt,d.deregAll=rt,d.eq=a,d.equals=G,d.extend=B,d.filter=ct,d.find=ft,d.flatten=St,d.flattenR=yt,d.fnToString=zt,d.forEach=M,d.fromJson=N,d.functionToString=Gt,d.getLocals=Bi,d.getNg1ViewConfigFactory=pi,d.getParams=Hn,d.hashLocationPlugin=ui,d.hostRegex=Xt,d.identity=z,d.inArray=K,d.inherit=Q,d.invoke=v,d.is=h,d.isArray=x,d.isDate=j,d.isDefined=E,d.isFunction=T,d.isInjectable=H,d.isNull=_,d.isNullOrUndefined=C,d.isNumber=P,d.isObject=O,d.isPromise=A,d.isRegExp=V,d.isString=k,d.isUndefined=b,d.joinNeighborsR=ie,d.kebobString=Bt,d.keyValsToObjectR=Vn,d.locationPluginFactory=Ln,d.makeEvent=$r,d.makeStub=I,d.map=ht,d.mapObj=lt,d.matchState=_r,d.maxLength=Lt,d.memoryLocationPlugin=ci,d.mergeR=it,d.ng1ViewsBuilder=di,d.noop=W,d.not=l,d.omit=ut,d.or=o,d.padString=Mt,d.pairs=Et,d.parse=R,d.parseUrl=Fn,d.pattern=g,d.pick=at,d.pipe=c,d.pluck=st,d.prop=m,d.propEq=y,d.pushR=gt,d.pushStateLocationPlugin=si,d.pushTo=tt,d.removeFrom=Z,d.resolvablesBuilder=ir,d.resolvePolicies=Fe,d.root=U,d.services=D,d.servicesPlugin=ai,d.silenceUncaughtInPromise=jt,d.silentRejection=Vt,d.splitEqual=re,d.splitHash=te,d.splitOnDelim=ne,d.splitQuery=ee,d.stringify=Qt,d.stripLastPathElement=Yt,d.tail=Pt,d.toJson=L,d.trace=we,d.trimHashVal=Zt,d.uniqR=wt,d.unnest=_t,d.unnestR=mt,d.val=p,d.values=pt,d.watchDigests=Ui,Object.defineProperty(d,"__esModule",{value:!0})});
//# sourceMappingURL=angular-ui-router.min.js.map;
(function () {

    angular.module("MWPApp")
        .config(uiRouterConfig)

    uiRouterConfig.$inject = ['$stateProvider', '$locationProvider','enrollmentSummaryModes'];

    function uiRouterConfig($stateProvider, $locationProvider, enrollmentSummaryModes) {
        const enrollmentSummaryState = {
            name: 'enrollmentSummary',
            url: '/summary',
            views: {
                enrollmentSummaryContent: {
                    component: 'enrollmentSummary'
                }

            },
            params: {
                editSaveSuccessful: undefined,
                addSaveSuccessful: undefined
            }
        }

        const enrollmentSummaryDependentDetailState = {
            name: 'enrollmentDependentSummary',
            url: '/dependent-detail',
            views: {
                enrollmentSummaryContent: {
                    component: 'enrollmentSummary'
                }

            },
            params: {
                data: undefined,
                editSaveSuccessful: undefined,
                mode: enrollmentSummaryModes.VIEWING_DEPENDENT, 
            },
            resolve: {
                previousState: ["$state", getPreviousState]
            },
            onEnter: ["$stateParams", "$state", function ($stateParams, $state) {
                if ($stateParams.data === undefined)
                    return $state.target("enrollmentSummary");
            }]
        }

        const addEnrollmentSummaryState = {
            name: 'addEnrollmentSummary',
            url: '/add-dependent',
            views: {
                enrollmentSummaryContent: {
                    component: 'addEnrollmentSummary',
                }
            },
            params: {
                data: undefined,
                mode: undefined,
                hasDependents: undefined,
                isUserSubscriber: undefined,
                backToText: undefined,
                billingCycleType: undefined,
                billingCycleTypeName: undefined
            },
            resolve: {
                previousState: ["$state", getPreviousState]
            },
            onEnter: ["$stateParams", "$state", function ($stateParams, $state) {
                if ($stateParams.data === undefined)
                    return $state.target("enrollmentSummary");
            }]
        };

        const editEnrollmentSummaryState = {
            name: 'editEnrollmentSummary',
            url: '/edit-{type}',
            views: {
                enrollmentSummaryContent: {
                    component: 'editEnrollmentSummary',
                }

            },
            params: {
                data: undefined,
                mode: undefined,
                hasDependents: undefined,
                isUserSubscriber: undefined,
                backToText: undefined,
            },
            resolve: {
                previousState: ["$state", getPreviousState]
            },
            onEnter: ["$stateParams", "$state", function ($stateParams, $state) {
                if ($stateParams.data === undefined)
                    return $state.target("enrollmentSummary");
            }]
        }

        $stateProvider.state(enrollmentSummaryState);
        $stateProvider.state(enrollmentSummaryDependentDetailState);
        $stateProvider.state(addEnrollmentSummaryState);
        $stateProvider.state(editEnrollmentSummaryState);

        $locationProvider.html5Mode({
            //to fix url configuration
            enabled: false,
            requireBase: false
        });
    }

    function getPreviousState($state) {
        return {
            name: $state.current.name,
            params: angular.copy($state.params),
            url: $state.href($state.current.name, $state.params)
        }
    }
})();
(function () {

    angular.module("MWPApp")
        .config(uiRouterConfig);

    uiRouterConfig.$inject = ["$stateProvider", "$locationProvider"];

    function uiRouterConfig($stateProvider, $locationProvider) {
        const planManagementState = {
            name: "planManagement",
            url: "/mangement",
            views: {
                planManagementContent: {
                    component: "planManagement"
                }
            }
        };

        const addNewPlanState = {
            name: 'addNewPlanPage',
            url: '/newplan',
            views: {
                planManagementContent: {
                    component: 'addNewPlan'
                }
            },
            params: {
                planTypes: undefined,
                effectiveDate: undefined,
                premiumGroup: undefined,
                insuredEnrollee: undefined,
                dependents: undefined,
                subscriberPlans: undefined,
                billingCycleType: undefined
            }
        }

        const changePlanState = {
            name: 'changePlanPage',
            url: '/changeplan',
            views: {
                planManagementContent: {
                    component: 'changePlan'
                }
            },
            params: {
                effectiveDate: undefined,
                planSelected: undefined,
                premiumGroup: undefined,
                dependents: undefined,
                subscriberPlans: undefined,
                billingCycleType: undefined
            }
        }

        $stateProvider.state(planManagementState);
        $stateProvider.state(addNewPlanState);
        $stateProvider.state(changePlanState);

        $locationProvider.html5Mode({
            enabled: false,
            requireBase: false
        });
    }
})();;
(function () {
    angular.module("MWPApp")
        .constant("enrollmentSummaryModes", {
            SUBSCRIBER: 1,          // user is subscriber, 
            VIEWING_DEPENDENT: 2,   // user is subscriber viewing dependent, 
            DEPENDENT: 3,           // user is dependent
            EDIT_SUBSCRIBER: 4,     // edit subscriber
            EDIT_DEPENDENT: 5       // edit dependent
        });
})();;
(function () {
    'use strict';
    angular
        .module('MWPApp')
        .component('addDocument', {
            templateUrl: '/MWP/Template/AddDocument',
            controller: AddDocumentCtrl,
            controllerAs: 'vm',
            bindings: {
                description: '<',
                enrolleeId: '<?',
                insurerId: '<?',
                qualifyingEventType: '<?',
                documents: '=',
                deferUpload: '<?',
                onDeferUpload: '=?',
                deferDocumentsToUpload: '=?',
                isRequired: '<?',
                isRequiredFailed: '<?',
                metadata: '<?'
            }
        });
    AddDocumentCtrl.$inject = ['AddDocumentService', 'Upload', 'ImpersonateService'];

    function AddDocumentCtrl(addDocumentService, upload, impersonateService) {
        const DOCUMENT_STATUS_CREATED = 0;
        const DOCUMENT_STATUS_MARKED_FOR_DELETION = 30;
        const DOCUMENT_TYPE_OTHER = 49;
        const MEGABYTE_VALUE = 1048576;
        const DECIMAL_FIXED_VALUE = 1;
        var vm = this;
        vm.$onInit = $onInit;
        vm.onUpload = onUpload;
        vm.showFixedFileSize = showFixedFileSize;
        vm.deleteDocument = deleteDocument;
        vm.onDeferUpload = uploadFiles;
        vm.deleteDeferDocument = deleteDeferDocument;
        function $onInit() {
            vm.uploadingText = "AddDocument_UploadingText";
            vm.maxUploadFileSize = 0;
            vm.rejectedFiles = [];
            vm.nonSuccessUploadFiles = [];
            vm.uploadResult = "";
            vm.allowedUploadFileTypes = "";
            vm.allowedUploadFileTypesDisplayMsg = "";
            getFileUploadConfiguration();
            vm.deferDocumentsToUpload = [];
            vm.documents = vm.documents || [];

            impersonateService.getImpersonateSessionInfo()
                .then(function (response) {
                    vm.isImpersonation = response.IsImpersonation;
                });
        };

        function onUpload(files) {
            if (!files || files.length === 0) {
                resetUploadFilesPanel();
                return;
            }

            if (vm.deferUpload === true) {
                for (var i = 0; i < files.length; i++) {
                    vm.deferDocumentsToUpload.push(files[i]);
                }
                return;
            }
            uploadFiles(files);
        };

        function uploadFiles(files, enrolleeId) {
            if (!vm.isImpersonation) {
                const defaultMetadata = { "QUALIFYING_EVENT_TYPE": vm.qualifyingEventType };
                const metadata = vm.metadata || defaultMetadata;
                return upload.upload({
                    url: "/api/UploadApi/UploadFiles",
                    data: {
                        enrolleeId: vm.enrolleeId || enrolleeId,
                        documentStatus: DOCUMENT_STATUS_CREATED,
                        documentTypeId: DOCUMENT_TYPE_OTHER,
                        metaData: metadata
                    },
                    file: files
                })
                    .progress(function (progressEvent) {
                        showProgressFileUpload(progressEvent);
                    })
                    .success(function (response) {
                        if (response === null || response.successUpload === null || response.nonSuccessUpload === null) return;

                        if (response.successUpload.length > 0) {
                            vm.uploadResult = "";
                            vm.uploadingFiles = [];
                            addUploadedDocumentsToGrid(response.successUpload);
                        }

                        if (response.nonSuccessUpload.length > 0) {
                            vm.uploadingFiles = [];
                            showFailedFiles(response.nonSuccessUpload);
                        }

                    })
                    .error(function (data) {
                        if (data)
                            vm.uploadResult = "";
                    });
            }
        }

        function showFixedFileSize(fileSize) {
            return (fileSize / MEGABYTE_VALUE).toFixed(DECIMAL_FIXED_VALUE);
        };

        function addUploadedDocumentsToGrid(documents) {
            for (var i = 0; i < documents.length; i++) {
                vm.documents.push({
                    documentId: documents[i].documentId,
                    fileName: documents[i].fileName
                });
            }
        }

        function getAllowedUploadFileTypes(extensions) {
            var extension = null;
            for (var i = 0; i < extensions.length; i++) {
                extension = extensions[i].toLowerCase();
                if (vm.allowedUploadFileTypes.length > 0) {
                    vm.allowedUploadFileTypes += ",";
                    vm.allowedUploadFileTypesDisplayMsg += ", ";
                }
                vm.allowedUploadFileTypes += "*.";
                vm.allowedUploadFileTypes += extension;
                vm.allowedUploadFileTypesDisplayMsg += extension;
            }
        }

        function getFileUploadConfiguration() {
            addDocumentService.getFileUploadConfiguration()
                .then(function (response) {
                    if (response === null) return;
                    vm.maxUploadFileSize = response.maxUploadFileSize;
                    getAllowedUploadFileTypes(response.allowedUploadFileTypes);
                });
        }

        function showProgressFileUpload(progressEvent) {
            if (progressEvent === null) return;
            vm.uploadingFiles = [];
            var files = progressEvent.config.file, file = null, progressPercentage = 0;
            for (var i = 0; i < files.length; i++) {
                file = files[i];
                progressPercentage = parseInt(100 * progressEvent.loaded / progressEvent.total);
                vm.uploadingFiles.push({ name: file.name, type: file.type, progressPercentage: progressPercentage });
            }
        }

        function showFailedFiles(nonSuccessUploadFiles) {
            var nonSuccessUploadFile = null;
            vm.nonSuccessUploadFiles = [];
            for (var i = 0; i < nonSuccessUploadFiles.length; i++) {
                nonSuccessUploadFile = nonSuccessUploadFiles[i];
                vm.nonSuccessUploadFiles.push({ name: nonSuccessUploadFile.fileName, statusMessage: nonSuccessUploadFile.statusMessage });
            }
        }

        function resetUploadFilesPanel() {
            vm.uploadingFiles = [];
            vm.nonSuccessUploadFiles = [];
        }

        function removeDocumentByDocumentId(documentId) {
            var index = vm.documents.findIndex(function (document) {
                return document.documentId === documentId;
            });

            if (index === -1) return;
            vm.documents.splice(index, 1);
        }

        function deleteDocument(documentId) {
            addDocumentService.deleteDocument(documentId, DOCUMENT_STATUS_MARKED_FOR_DELETION)
                .then(function (response) {
                    if (response === null) return;
                    removeDocumentByDocumentId(documentId);
                });
        }

        function deleteDeferDocument(name) {
            var index = vm.deferDocumentsToUpload.findIndex(function (document) {
                return document.name === name;
            });

            if (index === -1) return;
            vm.documents.splice(index, 1);
        }
    }
})();;
(function () {
    'use strict';
    angular.module('MWPApp')
        .component('contextBar',
        {
            templateUrl: '/Templates/MWP/ContextBarNav',
            controller: contextBar,
            controllerAs: 'vm',
            bindings: {
                'GroupId': '='
            }
        });
    contextBar.$inject = ['DataService', '$location', '$http', '$q'];

    function contextBar(DataService, $location, $http, $q) {
        var vm = this;
        vm.planName = DataService.PlanName;
        vm.url = $location.absUrl();
        var sessionProperties = [];
        var sessionProperty =
            {
                SESSION_NAME: 'Origin_URL',
                SESSION_VALUE: vm.url
            }
        sessionProperties.push(sessionProperty);

        vm.$onInit = function () {
        }
        vm.changePlan = function () {
            var promise = vm.setSessionProperties(sessionProperties);
            promise.then(function () {
                window.location = "/MWP/SelectGroup";
            }, function (data) {
            });

        }

        vm.setSessionProperties = function (sessionProperties) {
            var deferred = $q.defer();

            $http({
                url: "/PortalWebSession/SetWebSessionProperties",
                method: "PUT",
                data: {
                    SESSION_PROPERTIES: sessionProperties
                }
            }).then(function successCallback(response) {
                if (!response.data.Status) {
                    deferred.reject(false);
                    console.error(response.data.Message);
                    console.error(response);
                    vm.ExceptionDialogControl.showDialog("Error with setting session properties.");
                }
                else {
                    deferred.resolve(true);
                }
            }, function errorCallback(response) {
                deferred.reject(false);
                console.error(response.data.Message);
                console.error(response);
                vm.ExceptionDialogControl.showDialog("Error with setting session properties.");
            });

            return deferred.promise;
        }

    }

})();;
(function () {
    'use strict';
    angular.module('MWPApp')
        .component('memberDropDown',
        {
            templateUrl: '/Templates/MWP/MemberDdl',
            controller: memberDropDown,
            controllerAs: 'vm',
            bindings: {
                'memberInfo': '='
            }
        });
    memberDropDown.$inject = ['API', 'DataService', '$timeout'];

    function memberDropDown(API, DataService, $timeout) {
        var vm = this;
        vm.member = [];
        vm.memberInfo = {};

        vm.$onInit = function () {
            API.get('/MWP/PrintIDCard/GetEnrolleeDependents'
            ).then(
                function (result) {
                    for (var i = 0; i < result.length; i++) {
                        vm.member.push({ ENROLLEE_ID: result[i].enrolleeId, NAME: result[i].name });
                        if (result[i].enrolleeId == DataService.EnrolleeId) {
                            vm.memberId = vm.member[i].ENROLLEE_ID;
                            vm.SelectedChange(vm.memberId);
                        }
                    };

                });
        }

        vm.SelectedChange = function (data) {
            var EnrolleeId = data;
            API.get('/MWP/RequestID/GetMemberInfo?enrolleeId=' + EnrolleeId).then(function (success) {
                vm.memberInfo =
                {
                        selectedEnrolleeId: EnrolleeId,
                        memberId: success.ENROLLEE_ID,
                        memberName: success.FIRST_NAME + " ",
                        memberNameLast: " " + success.LAST_NAME,
                        memberAddress: success.ADDRESS1,
                        memberAddress2: success.ADDRESS2,
                        memberFullAddress: success.CITY + ", " + success.STATE + " " + success.ZIP,
                        memberNameMiddle: success.MIDDLE_NAME ? success.MIDDLE_NAME : success.MIDDLE_NAME = ""
                    }
            });
        }
    }
})();;
(function () {
    'use strict';

    angular
        .module("MWPApp")
        .filter("startFrom", function () {
            return (input, start) => {
                start = +start;
                return input.slice(start)
            }
        })

    angular
        .module('MWPApp')
        .component('accumulatorInformation', {
            templateUrl: '/MWP/Template/AccumulatorInformation',
            controller: accumulatorInformation,
            controllerAs: 'vm',
            bindings: {
                enrolleeId: '<',
                productId: '<',
                groupId: '<'
            }
        });
    accumulatorInformation.$inject = ['AccumulatorInformationService'];
    function accumulatorInformation(accumulatorInformationService) {
        var vm = this;

        const ACCUMULATOR_INFO_LIFETIME_MAXIMUMS_TEXT = "AccumulatorInformation_LifetimeMaximums";
        const ACCUMULATOR_INFO_ANNUAL_MAXIMUMS_TEXT = "AccumulatorInformation_AnnualMaximums";
        const ACCUMULATOR_INFO_LIFETIME_DEDUCTIBLES_TEXT = "AccumulatorInformation_LifetimeDeductibles";
        const ACCUMULATOR_INFO_ANNUAL_DEDUCTIBLES_TEXT = "AccumulatorInformation_AnnualDeductibles";
        const ACCUMULATOR_INFO_OUT_OF_POCKET_MAX_TEXT = "AccumulatorInformation_OutOfPocketMax";
        const ANNUAL = "Annual";
        const MEMBER_VALUE = "AccumulatorInformation_Member";
        const FAMILY_VALUE = "AccumulatorInformation_Family";
        const BENEFIT_MAXIMUS = "BenefitMaximums";
        const DEDUCTIBLES = "Deductibles";
        const OOP_MAXIMUS = "OopMaximums";

        vm.$onInit = onInit;
        vm.nextPage = nextPage;
        vm.previousPage = previousPage;
        vm.getSatisfiedAmount = getSatisfiedAmount;
        vm.getAmountTextDescriptor = getAmountTextDescriptor;
        vm.getFamilyMaximumnAmount = getFamilyMaximumnAmount;
        vm.getMemberMaximumnAmount = getMemberMaximumnAmount;
        vm.getMaximumnAmount = getMaximumnAmount;
        vm.getPercentage = getPercentage;
        vm.getCodesetDescription = getCodesetDescription;
        vm.onChangeFilter = onChangeFilter;
        vm.getAccummulatorList = getAccummulatorList;
        function onInit() {
            vm.benefitLevelTierItems = [
                {
                    text: 'AccumulatorInformation_InNetwork',
                    value: 1
                },
                {
                    text: 'AccumulatorInformation_OutofNetwork',
                    value: 2
                }
            ]
            vm.selectedBenefitLevelTier = vm.benefitLevelTierItems[0];

            vm.contractTypeItems = [
                {
                    text: 'AccumulatorInformation_Individual',
                    value: MEMBER_VALUE
                },
                {
                    text: 'AccumulatorInformation_Family',
                    value: FAMILY_VALUE
                }
            ]
            vm.selectedContractType = vm.contractTypeItems[0];

            vm.currentPage = 0;
            vm.pageSize = 4;
            vm.numberOfPages = 0;

            vm.accummulatorInformation = {};
            vm.accumulatorItems = [];
            getAccumulatorInformationDetail();
        }

        function getAccumulatorInformationDetail() {
            accumulatorInformationService.getAccumulatorInformationDetail({
                enrolleeId: vm.enrolleeId,
                productId: vm.productId,
                groupId: vm.groupId
            }).then(data => {
                vm.flags = {
                    deductiblesFlag: data.Product.DeductibleFlag,
                    benefitMaximunsFlag: data.Product.AnnualMaximumsFlag,
                    oopMaximunsFlag: data.Product.OopMaximumsFlag,
                }
                vm.accummulatorInformation = data;
                vm.accumulatorItems = [
                    ...(vm.flags.benefitMaximunsFlag
                        ? data.BenefitMaximums.map(item => getAccumulatorWithDetails(BENEFIT_MAXIMUS, item))
                        : []),
                    ...(vm.flags.deductiblesFlag
                        ? data.Deductibles.map(item => getAccumulatorWithDetails(DEDUCTIBLES, item))
                        : []),
                    ...(vm.flags.oopMaximunsFlag
                        ? data.OopMaximums.map(item => getAccumulatorWithDetails(OOP_MAXIMUS, item))
                        : []),
                ];
                onChangeFilter();
            });
        }

        function nextPage() {
            vm.currentPage++;
        }

        function previousPage() {
            vm.currentPage--;
        }


        function getAccumulatorWithDetails(type, accumulatorInfo) {
            return {
                ...accumulatorInfo,
                title: getTitle(type, accumulatorInfo),
                type: type
            };
        }

        function getTitle(type, accumulatorInfo) {
            let accumulatorTitle = "";

            if (type === BENEFIT_MAXIMUS) {
                accumulatorTitle = accumulatorInfo.BenefitPeriodTypeDescription === ANNUAL
                    ? ACCUMULATOR_INFO_ANNUAL_MAXIMUMS_TEXT
                    : ACCUMULATOR_INFO_LIFETIME_MAXIMUMS_TEXT;
            } else {
                accumulatorTitle = accumulatorInfo.BenefitPeriodTypeDescription !== undefined
                    ? accumulatorInfo.BenefitPeriodTypeDescription === ANNUAL
                        ? ACCUMULATOR_INFO_ANNUAL_DEDUCTIBLES_TEXT
                        : ACCUMULATOR_INFO_LIFETIME_DEDUCTIBLES_TEXT
                    : "";
                accumulatorTitle += type !== DEDUCTIBLES ? ACCUMULATOR_INFO_OUT_OF_POCKET_MAX_TEXT : "";
            }
            return accumulatorTitle;
        }

        function getCodesetDescription(codesetDescription) {
            return codesetDescription.length > 0 ? ` - ${codesetDescription}` : codesetDescription;
        }

        function getSatisfiedAmount(accumulatorInfo) {
            return vm.selectedContractType.value === FAMILY_VALUE
                ? accumulatorInfo.FamilySatisfiedAmount
                : accumulatorInfo.MemberSatisfiedAmount;
        }

        function getAmountTextDescriptor(accumulatorInfo) {
            const translationkey = accumulatorInfo.type === BENEFIT_MAXIMUS
                ? 'AccumulatorInformation_Used'
                : 'AccumulatorInformation_Paid';
            return translationkey;
        }
        function getFamilyMaximumnAmount(accumulatorInfo) {
            if (accumulatorInfo.type == BENEFIT_MAXIMUS)
                return accumulatorInfo.FamilyMaximumAmount;
            if (accumulatorInfo.type == DEDUCTIBLES)
                return accumulatorInfo.FamilyDeductibleAmount;
            if (accumulatorInfo.type == OOP_MAXIMUS)
                return accumulatorInfo.FamilyOopAmount;
        }

        function getMemberMaximumnAmount(accumulatorInfo) {
            if (accumulatorInfo.type == BENEFIT_MAXIMUS)
                return accumulatorInfo.MemberMaximumAmount;
            if (accumulatorInfo.type == DEDUCTIBLES)
                return accumulatorInfo.MemberDeductibleAmount;
            if (accumulatorInfo.type == OOP_MAXIMUS)
                return accumulatorInfo.MemberOopAmount;
        }

        function getMaximumnAmount(accumulatorInfo) {
            return vm.selectedContractType.value === FAMILY_VALUE
                ? vm.getFamilyMaximumnAmount(accumulatorInfo)
                : vm.getMemberMaximumnAmount(accumulatorInfo);
        }

        function getPercentage(accumulatorInfo) {
            return (getSatisfiedAmount(accumulatorInfo) / getMaximumnAmount(accumulatorInfo)) * 100;
        }

        function getAccummulatorList() {
            const isMemberContract = vm.selectedContractType.value === MEMBER_VALUE;
            return vm.accumulatorItems
                .filter(x => x.BenefitLevelTier == vm.selectedBenefitLevelTier.value)
                .filter(x => isMemberContract || x.FamilySatisfiedAmount !== null)
                .filter(x => (isMemberContract ? getMemberMaximumnAmount(x) : getFamilyMaximumnAmount(x)) !== null)
                ;
        }

        function onChangeFilter() {
            const listLength = getAccummulatorList().length;
            vm.numberOfPages = Math.ceil(listLength / vm.pageSize)
            vm.currentPage = 0;
        }
    }
})();;
(function () {
    'use strict';
    angular
        .module('MWPApp')
        .component('beneficiariesGrid', {
            templateUrl: '/MWP/Beneficiaries/BeneficiariesGrid',
            controller: beneficiariesGrid,
            controllerAs: 'vm',
            bindings: {
                isPrimaryBeneficiary: '<',
                successMessage: '=',
                pageMode: '=',
                enrolleeLifeInsuranceBeneficiaryId: '=',
                beneficiaryData: '=',
                reloadBanner: '='
            }
        });
    beneficiariesGrid.$inject = ['BeneficiariesService', 'WbxModalService', 'ImpersonateService'];

    function beneficiariesGrid(beneficiariesService, wbxModalService, impersonateService) {
        const vm = this;

        const MAXIMUM_TOTAL_PERCENTAGE = 100;
        const MINIMUM_TOTAL_PERCENTAGE = 0;
        const TEXT_COLOR = {
            success: 'wbx-success-color',
            danger: 'wbx-danger-color'
        };
        const ADD_PRIMARY_BENEFICIARY_TITLE = "Beneficiaries_AddPrimaryBeneficiaryButton";
        const ADD_CONTINGENT_BENEFICIARY_TITLE = "Beneficiaries_AddContingentBeneficiaryButton";
        const CANT_ADD_PRIMARY_TOOLTIP = "Beneficiaries_TooltipMaximunAllocationPrimary";
        const CANT_ADD_CONTINGENT_TOOLTIP = "Beneficiaries_TooltipMaximunAllocationContingent";
        const ADD_PAGE_MODE = 1;
        const EDIT_PAGE_MODE = 2;
        const DELETE_PAGE_MODE = 3;

        vm.$onInit = onInit;
        vm.promptDeleteBeneficiary = promptDeleteBeneficiary;
        vm.mobileDeleteBeneficiary = mobileDeleteBeneficiary;
        vm.openAddBeneficiaryModal = openAddBeneficiaryModal;
        vm.mobileAddBeneficiary = mobileAddBeneficiary;
        vm.openEditBeneficiaryModal = openEditBeneficiaryModal;
        vm.mobileEditBeneficiary = mobileEditBeneficiary;
        vm.canAdd = canAdd;
        vm.getCantAddKeyTranslation = getCantAddKeyTranslation;
        vm.getTranslationParams = getTranslationParams;

        function onInit() {
            impersonateService.getImpersonateSessionInfo()
                .then(function (response) {
                    vm.isImpersonation = response.IsImpersonation;
                });
            getBeneficiaries();
            getAddBeneficiaryButtonTitle();
        }

        function getBeneficiaries() {
            const beneficiariesInput = {
                IsPrimaryBeneficiary: vm.isPrimaryBeneficiary
            };

            beneficiariesService.getBeneficiaries(beneficiariesInput)
                .then(function (response) {
                    vm.beneficiariesGrid = response.data;
                    calculatePrimaryPercentage();
                    if (vm.reloadBanner) {
                        vm.reloadBanner();
                    }
                });
        }

        function calculatePrimaryPercentage() {
            vm.totalPercentage = 0;

            for (let primaryBeneficiary of vm.beneficiariesGrid) {
                vm.totalPercentage += primaryBeneficiary.Percentage;
            }

            if (vm.isPrimaryBeneficiary) {
                vm.getTotalColor = vm.totalPercentage === MAXIMUM_TOTAL_PERCENTAGE ? TEXT_COLOR.success : TEXT_COLOR.danger;
            } else {
                vm.getTotalColor = (vm.totalPercentage === MAXIMUM_TOTAL_PERCENTAGE || vm.totalPercentage === MINIMUM_TOTAL_PERCENTAGE) ? TEXT_COLOR.success : TEXT_COLOR.danger;
            }
        }

        function getAddBeneficiaryButtonTitle() {
            vm.addBeneficiaryButtonTitle = vm.isPrimaryBeneficiary ? ADD_PRIMARY_BENEFICIARY_TITLE : ADD_CONTINGENT_BENEFICIARY_TITLE;
        }

        function promptDeleteBeneficiary(beneficiary) {
            const modalDefaults = {
                component: "deleteBeneficiaryConfirmation",
                size: "sm",
                windowClass: "",
                resolve: {}
            };

            const beneficiaryDataParsed = parseGridBeneficiaryDataForForm(beneficiary);
            beneficiaryDataParsed.EnrolleeLifeInsuranceBeneficiaryId = beneficiary.EnrolleeLifeInsuranceBeneficiaryId;
            beneficiaryDataParsed.PrimaryBeneficiaryFlag = beneficiary.PrimaryBeneficiaryFlag;

            wbxModalService.showModal(modalDefaults)
                .then(function (response) {
                    if (response) {
                        deleteBeneficiary(beneficiaryDataParsed);
                    }
                });
        }

        function deleteBeneficiary(beneficiary) {
            beneficiariesService.deleteBeneficiary(beneficiary)
                .then(function (response) {
                    if (response.data.IsSuccess) {
                        vm.successMessage = response.data.Message;
                        getBeneficiaries();
                    }
                });
        }

        function mobileDeleteBeneficiary(beneficiary) {
            vm.beneficiaryData = beneficiary;
            vm.pageMode = DELETE_PAGE_MODE;
        }

        function openAddBeneficiaryModal() {
            openBeneficiaryModal(true, getAddBeneficiaryData());
        }

        function openEditBeneficiaryModal(beneficiary) {
            openBeneficiaryModal(false, parseGridBeneficiaryDataForForm(beneficiary));
        }

        function openBeneficiaryModal(isAdd, beneficiary) {
            const payload = {
                isAdd: isAdd,
                isModal: true,
                beneficiaryData: beneficiary
            };

            const modalDefaults = {
                component: "beneficiaryModal",
                size: "md",
                windowClass: "",
                resolve: {
                    payload: payload
                }
            };
            wbxModalService.showModal(modalDefaults, {})
                .then(function (result) {
                    if (result.success) {
                        vm.successMessage = result.data;
                        getBeneficiaries();
                    }
                });
        }

        function mobileAddBeneficiary() {
            showMobileBeneficiaryPage(true, getAddBeneficiaryData());
        }

        function mobileEditBeneficiary(beneficiary) {
            showMobileBeneficiaryPage(false, parseGridBeneficiaryDataForForm(beneficiary));
        }

        function showMobileBeneficiaryPage(isAdd, beneficiary) {
            vm.beneficiaryData = beneficiary;
            vm.pageMode = isAdd ? ADD_PAGE_MODE : EDIT_PAGE_MODE;
        }

        function canAdd() {
            return vm.totalPercentage < MAXIMUM_TOTAL_PERCENTAGE;
        }

        function getCantAddKeyTranslation() {
            return vm.isPrimaryBeneficiary ? CANT_ADD_PRIMARY_TOOLTIP : CANT_ADD_CONTINGENT_TOOLTIP;
        }

        function getAddBeneficiaryData() {
            return {
                isPrimary: vm.isPrimaryBeneficiary,
                percentage: getRemainingPercentage()
            };
        }

        function parseGridBeneficiaryDataForForm(beneficiary) {
            return {
                beneficiaryId: beneficiary.EnrolleeLifeInsuranceBeneficiaryId,
                isPrimary: beneficiary.PrimaryBeneficiaryFlag,
                percentage: beneficiary.Percentage,
                name: beneficiary.Name,
                dateOfBirth: beneficiary.DateOfBirth,
                relationship: beneficiary.Relationship,
            };
        }

        function getRemainingPercentage() {
            return MAXIMUM_TOTAL_PERCENTAGE - vm.totalPercentage;
        }

        function getTranslationParams(beneficiaryName) {
            return {
                beneficiaryName
            };
        };
    }
})();;
(function () {
    'use strict';
    angular
        .module('MWPApp')
        .component('beneficiaryForm', {
            templateUrl: '/MWP/Beneficiaries/BeneficiaryForm',
            controller: BeneficiaryCtrl,
            controllerAs: 'vm',
            bindings: {
                isAdd: '<',
                isModal: '<',
                beneficiaryData: '<',
                modalInstance: '<?',
                successMessage: '=?',
                pageMode: '=?'
            }
        });
    BeneficiaryCtrl.$inject = ['BeneficiariesService', '$timeout', 'ImpersonateService'];

    function BeneficiaryCtrl(beneficiariesService, $timeout, impersonateService) {
        const PRIMARY_INFORMATION_BANNER = "Beneficiaries_PrimaryInformationFormBanner";
        const CONTINGENT_INFORMATION_BANNER = "Beneficiaries_ContingentInformationFormBanner";
        const MAX_VALUE_PERCENTAGE = "100";
        const MIN_VALUE_PERCENTAGE = "1";

        const DEFAULT_PAGE_MODE = 0;
        const vm = this;
        vm.$onInit = $onInit;
        vm.save = save;
        vm.cancel = cancel;
        vm.getInformationBannerKeyTranslation = getInformationBannerKeyTranslation;
        vm.validateErrors = validateErrors;

        vm.controlsList = [
            {
                name: 'beneficiaryFormIdDateOfBirthTextBox',
                translation: 'Beneficiaries_DateOfBirth',
                overrideValidationsText: undefined
            },
            {
                name: 'beneficiaryFormIdNameTextBox',
                translation: 'Beneficiaries_Name',
                overrideValidationsText: undefined
            },
            {
                name: 'beneficiaryFormIdPercentageTextBox',
                translation: 'Beneficiaries_Percentage',
                overrideValidationsText: "{'maxValue': '((maxValue:" + MAX_VALUE_PERCENTAGE + "))', 'minValue': '((minValue: " + MIN_VALUE_PERCENTAGE + "))'}"
            }
        ];

        function $onInit() {
            vm.beneficiaryForm = {
                Percentage: vm.beneficiaryData.percentage,
                Name: vm.beneficiaryData.name,
                DateOfBirth: vm.beneficiaryData.dateOfBirth,
                Relationship: vm.beneficiaryData.relationship
            };
            impersonateService.getImpersonateSessionInfo()
                .then(function (response) {
                    vm.isImpersonation = response.IsImpersonation;
                });
        }

        function validateErrors() {
            if (vm.beneficiaryFormFormName.$invalid) {
                vm.beneficiaryFormErrors = getBeneficiaryErrorListForBanner(vm.beneficiaryFormFormName);
            }
        }

        function getBeneficiaryErrorListForBanner(beneficiaryForm) {
            const errors = [];
            vm.controlsList.forEach(function (control) {
                if (beneficiaryForm[control.name] === undefined) { return; }
                const inputErrorList = Object.keys(beneficiaryForm[control.name].$error);
                if (inputErrorList.length === 0) {
                    return;
                }

                errors.push({
                    wbxName: control.name,
                    labelKey: control.translation,
                    inputErrors: inputErrorList,
                    overrideValidationsText: control.overrideValidationsText
                });
            });
            return errors;
        }

        function save() {
            vm.error = undefined;
            vm.beneficiaryFormErrors = undefined;
            vm.beneficiaryFormFormName.$setSubmitted();

            if (vm.beneficiaryFormFormName.$invalid) {
                vm.beneficiaryFormErrors = getBeneficiaryErrorListForBanner(vm.beneficiaryFormFormName);
                return;
            }
            vm.isSaveDisabled = true;

            let payload = {
                EnrolleeLifeInsuranceBeneficiaryId: vm.isAdd ? null : vm.beneficiaryData.beneficiaryId,
                PrimaryBeneficiaryFlag: vm.beneficiaryData.isPrimary,
                Name: vm.beneficiaryForm.Name,
                DateOfBirth: vm.beneficiaryForm.DateOfBirth,
                Relationship: vm.beneficiaryForm.Relationship,
                Percentage: vm.beneficiaryForm.Percentage
            };

            let promise = vm.isAdd ? beneficiariesService.addBeneficiary(payload) : beneficiariesService.editBeneficiary(payload);

            promise.then(function (response) {
                if (response.IsSuccess) {
                    if (vm.isModal)
                        vm.modalInstance.close({ success: true, data: response.Message });
                    else {
                        vm.successMessage = response.Message;
                        switchToDefaultPage();
                    }
                } else {
                    vm.error = response.Message;
                }
            }).finally(function () {
                vm.isSaveDisabled = false;
                $timeout(function () {
                    angular.element('#SaveButton').focus();
                });                
            });
        }
        function cancel() {
            if (vm.isModal)
                vm.modalInstance.dismiss();
            else
                switchToDefaultPage();
        }
        function switchToDefaultPage() {
            vm.pageMode = DEFAULT_PAGE_MODE;
        }
        function getInformationBannerKeyTranslation() {
            return vm.beneficiaryData.isPrimary ? PRIMARY_INFORMATION_BANNER : CONTINGENT_INFORMATION_BANNER;
        }
    }
})();;
(function () {
    'use strict';
    angular
        .module('MWPApp')
        .component('beneficiaryModal', {
            templateUrl: '/MWP/Beneficiaries/BeneficiaryModal',
            controller: BeneficiaryModalCtrl,
            controllerAs: 'vm',
            bindings: {
                resolve: '<',
                modalInstance: '<'
            }
        });
    BeneficiaryModalCtrl.$inject = [];

    function BeneficiaryModalCtrl() {
        const ADD_KEY = "Beneficiaries_Add";
        const EDIT_KEY = "Beneficiaries_Edit";
        const PRIMARY_KEY = "Beneficiaries_Primary";
        const CONTINGENT_KEY = "Beneficiaries_Contingent";
        const vm = this;
        vm.$onInit = $onInit;
        vm.cancel = cancel;

        function $onInit() {
            vm.payload = vm.resolve.payload;
            vm.actionText = vm.payload.isAdd === true ? ADD_KEY : EDIT_KEY;
            vm.typeText = vm.payload.beneficiaryData.isPrimary === true ? PRIMARY_KEY : CONTINGENT_KEY;
        }

        function cancel() {
            vm.modalInstance.dismiss();
        }
    }
})();;
(function () {
    'use strict';
    angular
        .module('MWPApp')
        .component('deleteBeneficiaryConfirmation', {
            controller: deleteBeneficiaryConfirmation,
            controllerAs: 'vm',
            templateUrl: '/MWP/Beneficiaries/DeleteBeneficiaryConfirmation',
            bindings: {
                modalInstance: '<?',
                pageMode: '=',
                beneficiaryData: '<',
                successMessage: '='
            }
        });

    deleteBeneficiaryConfirmation.$inject = ['BeneficiariesService', 'ImpersonateService'];

    function deleteBeneficiaryConfirmation(beneficiariesService, impersonateService) {
        const vm = this;
        const DEFAULT_PAGE_MODE = 0;
        const SUBMITTED = true;

        vm.$onInit = $onInit;
        vm.cancel = cancel;
        vm.submit = submit;
        vm.goBack = goBack;
        vm.submitMobile = submitMobile;

        function $onInit() {
            impersonateService.getImpersonateSessionInfo()
                .then(function (response) {
                    vm.isImpersonation = response.IsImpersonation;
                });
        }

        function cancel() {
            vm.modalInstance.dismiss();
        }

        function submit() {
            vm.modalInstance.close(SUBMITTED);
        }

        function goBack() {
            vm.pageMode = DEFAULT_PAGE_MODE;
        }

        function submitMobile() {
            deleteBeneficiary(vm.beneficiaryData);
        }

        function deleteBeneficiary(beneficiary) {
            beneficiariesService.deleteBeneficiary(beneficiary)
                .then(function (response) {
                    if (response.data.IsSuccess) {
                        vm.successMessage = response.data.Message;
                        vm.pageMode = DEFAULT_PAGE_MODE;
                    }
                });
        }
    }
})();;
(function () {
    'use strict';
    angular
        .module('MWPApp')
        .component('beneficiaryDesignation', {
            templateUrl: '/MWP/Beneficiaries/BeneficiaryDesignationBanner',
            controller: beneficiaryDesignationController,
            controllerAs: 'vm',
            bindings: {
                reloadBanner: '=?'
            }
        });

    beneficiaryDesignationController.$inject = ['BeneficiaryDesignationService', '$window'];
    function beneficiaryDesignationController(beneficiaryDesignationService, $window) {
        const TARGET_WINDOW_SELF = "_self";

        const vm = this;

        vm.$onInit = $onInit;
        vm.goToViewBeneficiaries = goToViewBeneficiaries;
        vm.reloadBanner = showBeneficiaryDesignationBanner;

        function $onInit() {
            showBeneficiaryDesignationBanner();
        }

        function showBeneficiaryDesignationBanner() {
            beneficiaryDesignationService.showBeneficiaryDesignationBanner()
                .then(function (response) {
                    vm.showBeneficiaryDesignationBannerFlag = response.data;
                });
        }

        function goToViewBeneficiaries() {
            const beneficiariesUrl = "https://" + $window.location.host + "/MWP/Beneficiaries";
            $window.open(beneficiariesUrl, TARGET_WINDOW_SELF);
        }
    }
})();;
(function () {
    'use strict';
    angular
        .module('MWPApp')
        .component('updateBillingFrequencyModal', {
            templateUrl: '/MWP/BillingInformation/UpdateBillingFrequencyModal',
            controller: updateBillingFrequencyModal,
            controllerAs: 'vm',
            bindings: {
                modalInstance: "<?"
            }
        });
    updateBillingFrequencyModal.$inject = ['BillingInformationService', 'ImpersonateService'];

    function updateBillingFrequencyModal(billingInformationService, impersonateService) {
        const BILLING_FREQUENCY_DEFAULT_MONTH = "1";
        const SUCCESS_MESSAGE = "EnrollmentSummary_UpdateBillingFrequencySuccessMessage";

        var vm = this;

        vm.updateBillingFrequencyFilter = {
            BillingCycle: BILLING_FREQUENCY_DEFAULT_MONTH
        };

        vm.$onInit = onInit;
        vm.close = close;
        vm.updateBillingFrequency = updateBillingFrequency;

        function onInit() {
            loadBillingCycles();
            impersonateService.getImpersonateSessionInfo()
                .then(function (response) {
                    vm.isImpersonation = response.IsImpersonation;
                });
        }

        function loadBillingCycles() {
            billingInformationService.getBillingCycleMonthlyAndAnnually()
                .then(function (result) {
                    vm.updateBillingFrequencyFilter.BillingCycles = result.data;
                });
        }

        function close() {
            vm.modalInstance.close('close');
        }

        function updateBillingFrequency() {
            billingInformationService.updateBillingFrequency(vm.updateBillingFrequencyFilter.BillingCycle)
                .then(function (result) {
                    if (!result.IsSuccess) {
                        vm.errorMessage = result.Message;                      
                        return;
                    }

                    vm.modalInstance.close(SUCCESS_MESSAGE);                
                });
        }
    }
})();;
(function () {
    "use strict"
    angular
        .module("MWPApp")
        .component("terminateModalComponent", {
            templateUrl: "/MWP/Template/TerminateModal",
            controller: TerminateModalController,
            controllerAs: "vm",
            bindings: {
                modalInstance: "<",
                resolve: '<'
            }
        });

    TerminateModalController.$inject = ["TerminateModalService", "DataService", "wbxListErrorsService", "OpenEnrollmentService", "WbxModalService", "$rootScope"];

    function TerminateModalController(terminateModalService, dataService, wbxListErrorsService, openEnrollmentService, wbxModalService, $rootScope) {
        const QUALIFYING_EVENT_TYPE_TERMINATE = "Term subscriber";
        const QUALIFYING_EVENT_DATE_SUBSCRIBER_CANNOT_BE_TERMED_PAST = "Contract_SubscriberCannotBeTermed_QualifyingEventIsMore30DaysInThePast";
        const QUALIFYING_EVENT_DATE_PAST_INLINE = "Contract_TerminateSubscriberModal_QualifyingEventDatePast_Inline";
        const RENEWAL_PERIOD_CHANGE_TERMINATION_REASON_CODE = 10;

        let vm = this;
        vm.$onInit = init;
        vm.cancel = cancel;
        vm.eventDateValidationForTerminateContract = eventDateValidationForTerminateContract;
        vm.getTerminateContractModalPlansList = getTerminateContractModalPlansList;
        vm.terminateContractContinue = terminateContractContinue;
        vm.getPlansTranslationParams = getPlansTranslationParams;
        vm.qualifyingEventTypeTerminate = QUALIFYING_EVENT_TYPE_TERMINATE;
        vm.renewalPeriodChangeTerminationReasonCode = RENEWAL_PERIOD_CHANGE_TERMINATION_REASON_CODE;
        vm.changeQualifyingEventDropDependent = changeQualifyingEventDropDependent;
        vm.planChecked = planChecked;
        
        
        function init() {
            vm.enrolleeId = dataService.EnrolleeId;
            vm.terminateContractModalDocuments = [];
            vm.terminateContractModel = {
                EnrolleeId: vm.enrolleeId
            };
            vm.billingCycleType = undefined;

            vm.getTerminateContractModalPlansList(vm.enrolleeId);
            initTerminateContractForm();
            validateOpenEnrollment();
            vm.voicePhone = dataService.PortalInfo.VoicePhone;
            vm.customerServiceEmail = dataService.PortalInfo.CustomerServiceEmail;
            vm.isComingFromPlanManagement = vm.resolve.payload.isComingFromPlanManagement; 
            vm.isLoading = true;
        }

        function initTerminateContractForm() {
            vm.todayMinus30Days = moment().subtract(30, "days").format("MM/DD/yyyy");
            vm.terminateContractFormCustomErrors = {
                EventDateTextBox: {
                    isAfter: `${QUALIFYING_EVENT_DATE_SUBSCRIBER_CANNOT_BE_TERMED_PAST} {{ \\"voicePhone\\": \\"${dataService.get("PortalInfo")["VoicePhone"]}\\" , \\"email\\": \\"${dataService.get("PortalInfo")["CustomerServiceEmail"]}\\" }}`,
                }
            };
            vm.terminateContractFormCustomErrorsInline = {
                EventDateTextBox: {
                    isAfter: `${QUALIFYING_EVENT_DATE_PAST_INLINE}`,
                }
            };
        }

        function cancel() {
            vm.terminateContractFormCustomError = undefined;
            vm.terminateContractFormValidations = {};
            vm.modalInstance.close("cancel");
        }

        function getQualifyingEventsForTerminateContract() {
            terminateModalService.getQualifyingEventsTerminateContract(vm.isOpenEnrollmentFlag)
                .then(function successCallback(response) {
                    if (vm.isComingFromPlanManagement || vm.isOpenEnrollmentFlag) {
                        vm.terminateContractModel.QualifyingEvent = vm.renewalPeriodChangeTerminationReasonCode;
                    }

                    vm.qualifyingEventListForTerminateContract = response;

                    vm.isLoading = false;
                });
        }

        function eventDateValidationForTerminateContract() {
            if (!vm.terminateContractForm.$submitted)
                return;

            if (vm.terminateContractForm.$invalid || vm.terminateContractFormValidations.Invalid) {
                vm.terminateContractFormErrors = wbxListErrorsService.getErrorListForBanner(vm.terminateContractForm);
                return;
            }
        }

        function terminateContractCheckPlans() {
            vm.terminateContractFormValidations.plansRequired = false;
            if (!_.find(vm.terminateContractModel.Plans, function (obj) { return obj.Selected; })) {
                vm.terminateContractFormValidations.plansRequired = true;
                vm.terminateContractFormValidations.Invalid = true;
            }
        }

        function terminateContractCheckDocuments() {
            vm.terminateContractFormValidations.documentsRequired = false;
            if (vm.terminateContractModalDocuments.length === 0) {
                vm.terminateContractFormValidations.documentsRequired = true;
                vm.terminateContractFormValidations.Invalid = true;
            }
        }

        function getTerminateContractModalPlansList(enrolleeId) {
            const EMBEDDED_LIFE_INSURANCE_CATEGORY = 1;
            const LIFE_LINE_OF_BUSINESS = 9;
            vm.terminateContractModalNoPlans = undefined;
            vm.plansToNotTerminateString = "";

            terminateModalService.getEnrolleeActivePlans(enrolleeId).then(function (response) {
                vm.terminateContractModel.Plans = response;
                const plans = vm.isComingFromPlanManagement ? response.filter(plan => plan.TerminationDate === null || plan.TerminationDate === undefined) : response;

                if (plans.length) {
                    vm.terminateContractModel.Plans = plans.map(plan => {
                        plan.isDisabled = plan.LineOfBusiness === LIFE_LINE_OF_BUSINESS && plan.ProductLifeInsuranceCategoryId === EMBEDDED_LIFE_INSURANCE_CATEGORY;
                        plan.Selected = false;
                        plan.Description = plan.ProductName + " (" + plan.LineOfBusinessDescription + ")";
                        plan.CustomId = "plan_" + plan.PremiumGroupId + "_" + plan.ProductId;

                        return plan;
                    });
                }
                else {
                    vm.plansToNotTerminateString = dataService.PlanName;
                    vm.terminateContractModalNoPlans = {
                        message: "Contract_TerminateSubscriberModal_Exceeded_Term_Date"
                    };
                }
            });
        }

        function terminateContractContinue() {
            vm.terminateContractModalCustomError = undefined;
            vm.terminateContractModalCustomWarning = undefined;
            vm.terminateContractModalCustomWarningCombination = undefined;
            vm.terminateContractFormValidations = {};
            vm.terminateContractFormErrors = undefined;

            if (vm.terminateContractModel.QualifyingEvent === vm.renewalPeriodChangeTerminationReasonCode) {
                vm.terminateContractModel.EventDate = new Date(new Date().getFullYear(), new Date().getMonth(), new Date().getDate());
            }

            terminateContractCheckPlans();

            if (vm.terminateContractModel.QualifyingEvent !== vm.renewalPeriodChangeTerminationReasonCode) {
                terminateContractCheckDocuments();

                if (vm.terminateContractForm.$invalid || vm.terminateContractFormValidations.Invalid) {
                    vm.terminateContractFormErrors = wbxListErrorsService.getErrorListForBanner(vm.terminateContractForm);
                    return;
                }
            } else if (vm.terminateContractFormValidations.plansRequired && vm.terminateContractFormValidations.Invalid) {
                return;
            }

            validateTerminateSubscriber();
        }

        function validateTerminateSubscriber() {
            vm.terminateContractModalCustomError = undefined;
            vm.terminateContractModalCustomWarning = undefined;
            vm.terminateContractFormValidations = {};
            vm.terminateContractFormErrors = undefined;

            if (vm.terminateContractModel.QualifyingEvent === vm.renewalPeriodChangeTerminationReasonCode) {
                vm.terminateContractModel.EventDate = new Date(new Date().getFullYear(), new Date().getMonth(), new Date().getDate());
            }

            terminateContractCheckPlans();

            if (vm.terminateContractModel.QualifyingEvent !== vm.renewalPeriodChangeTerminationReasonCode) {
                terminateContractCheckDocuments();

                if (vm.terminateContractForm.$invalid || vm.terminateContractFormValidations.Invalid) {
                    vm.terminateContractFormErrors = wbxListErrorsService.getErrorListForBanner(vm.terminateContractForm);
                    return;
                }
            } else if (vm.terminateContractFormValidations.plansRequired && vm.terminateContractFormValidations.Invalid) {
                return;
            }

            let selectedPlans = "";
            let selectedPlansList = [];
            for (let i = 0; i < vm.terminateContractModel.Plans.length; i++) {
                if (vm.terminateContractModel.Plans[i].Selected) {
                    selectedPlans += vm.terminateContractModel.Plans[i].Description + ", ";
                    selectedPlansList.push(vm.terminateContractModel.Plans[i]);
                }
            }
            vm.terminateContractModel.SelectedPlans = selectedPlans.substr(0, selectedPlans.length - 2);

            let subscriber = {
                enrolleeId: vm.terminateContractModel.EnrolleeId,
                eventDate: vm.terminateContractModel.EventDate,
                plans: selectedPlansList,
                terminateReasonCode: vm.terminateContractModel.QualifyingEvent,
                premiumGroupId: dataService.GroupId,
                billingCycle: dataService.billingCycleType
            };

            terminateModalService.validateTerminateSubscriber(subscriber)
                .then(function (response) {
                    const dateReason = "date";
                    vm.terminateContractModel.plansToNotTerminate = response.data.plansToNotTerminate;
                    vm.terminateContractModel.plansToTerminate = response.data.plansToTerminate;
                    vm.terminateContractModel.terminationDate = response.data.terminationDate;
                    vm.terminateContractModel.newPrice = response.data.newPrice;
                    vm.terminateContractModel.memberIsGoingToBeBilled = response.data.memberIsGoingToBeBilled;

                    if (vm.terminateContractModel.plansToNotTerminate.length > 0) {
                        vm.plansToNotTerminateString = "";
                        for (let i = 0; i < vm.terminateContractModel.plansToNotTerminate.length; i++) {
                            if (vm.terminateContractModel.plansToNotTerminate[i].reasonToNotDrop === dateReason) {
                                vm.plansToNotTerminateString += vm.terminateContractModel.plansToNotTerminate[i].description + ", ";
                            }
                        }
                        vm.plansToNotTerminateString = vm.plansToNotTerminateString.substr(0, vm.plansToNotTerminateString.length - 2);
                        if (vm.plansToNotTerminateString !== "") {
                            vm.terminateContractModalCustomWarning = {
                                message: "Contract_TerminateSubscriberModal_Exceeded_Term_Date"
                            };
                        }
                    }

                    if (vm.terminateContractModel.plansToTerminate.length > 0) {
                        vm.plansToTerminateString = "";
                        for (let i = 0; i < vm.terminateContractModel.plansToTerminate.length; i++) {
                            vm.plansToTerminateString += vm.terminateContractModel.plansToTerminate[i].description + ", ";
                        }
                        vm.plansToTerminateString = vm.plansToTerminateString.substr(0, vm.plansToTerminateString.length - 2);
                        openConfirmationModal(subscriber);
                    }
                }, function (response) {
                    if (response.errors.Error_QualifyingDateInvalid) {
                        if (response.errors.Error_QualifyingDateInvalid[0] === QUALIFYING_EVENT_DATE_PAST) {
                            vm.terminateContractFormCustomErrors = {
                                Message: response.errors.Error_QualifyingDateInvalid[0],
                                ExtraData: response.errors.Data_QualifyingDateInvalid[0],
                                Params: { voicePhone: vm.voicePhone, email: vm.customerServiceEmail }
                            };
                            vm.terminateContractFormValidations.QualifyingEventDatePast = true;
                            vm.terminateContractFormValidations.EventDateTextBoxInvalid = true;
                            return;
                        }

                        if (response.errors.Error_QualifyingDateInvalid[0] === QUALIFYING_EVENT_DATE_FUTURE) {
                            vm.terminateContractFormValidations.Invalid = true;
                            vm.terminateContractFormValidations.QualifyingEventDateFuture = true;
                            vm.terminateContractFormValidations.EventDateTextBoxInvalid = true;
                            return;
                        }
                    }

                    if (response.errors.Error_CalculatedTerminationDateLessThanContractEndDate) {
                        vm.terminateContractError = true;
                        vm.terminateContractModalCalculatedTerminationDate = {
                            Message: response.errors.Error_CalculatedTerminationDateLessThanContractEndDate[0],
                            Params: {
                                billingFrequency: dataService.billingCycleTypeName,
                                customerServicePhone: dataService.PortalInfo.VoicePhone,
                                customerServiceEmail: dataService.PortalInfo.CustomerServiceEmail
                            }
                        };
                        return;
                    }
                });
        }

        function getPlansTranslationParams() {
            return { plans: vm.plansToNotTerminateString };
        }

        function validateOpenEnrollment() {
            vm.isOpenEnrollmentFlag = false;
            openEnrollmentService.getIsOpenEnrollment()
                .then(function successCallback(response) {
                    if (response) {
                        vm.isOpenEnrollmentFlag = response.isOpenEnrollment;
                    }

                    getQualifyingEventsForTerminateContract();
                });
        }

        function changeQualifyingEventDropDependent() {
            vm.terminateContractModalCustomError = undefined;
            vm.terminateContractModalCustomWarning = undefined;
            vm.terminateContractModalCustomWarningCombination = undefined;
            vm.terminateContractFormValidations = {};
            vm.terminateContractFormErrors = undefined;

            if (vm.terminateContractForm && vm.terminateContractModel.QualifyingEvent === vm.renewalPeriodChangeTerminationReasonCode) {
                vm.terminateContractForm.$setPristine(true);
                vm.terminateContractForm.$setUntouched(true);
            }
        }

        function getResponse(result, data) {
            return { result: result, data: data };
        }

        function openConfirmationModal(subscriber) {
            vm.modalInstance.close(getResponse("close"));

            let payload = {
                plansToTerminate: vm.terminateContractModel.plansToTerminate,
                plansToTerminateString: vm.plansToTerminateString,
                expirationDate: vm.terminateContractModel.terminationDate,
                subscriber: subscriber
            };

            let modalDefaults = {
                backdrop: "static",
                keyboard: true,
                modalFade: true,
                component: "terminateSubscriberConfirmationModalComponent",
                size: "md",
                windowClass: "",
                resolve: {
                    payload: function () { return payload; }
                }
            };
            wbxModalService.showModal(modalDefaults, {}).then(function (response) {
                if (response.result !== "submit") return;

                let terminateSubscriberInput = {
                    Products: response.data,
                    TerminationDate: vm.terminateContractModel.terminationDate,
                    TerminationReasonCode: vm.terminateContractModel.QualifyingEvent,
                    TerminationReasonEventDate: vm.terminateContractModel.EventDate,
                    DocumentIds: vm.terminateContractModel.QualifyingEvent === vm.renewalPeriodChangeTerminationReasonCode ? null : vm.terminateContractModalDocuments.map(x => x.documentId),
                    EnrolleeId: vm.terminateContractModel.EnrolleeId,
                }

                terminateModalService.terminateSubscriber(terminateSubscriberInput)
                    .then(function (responseTerminateSubscriber) {
                        $rootScope.$broadcast("terminateSubscriber", responseTerminateSubscriber);
                    });
            });
        }

        function planChecked(plan) {
            const DENTAL_LINE_OF_BUSINESS = 2;
            if (plan.LineOfBusiness === DENTAL_LINE_OF_BUSINESS && plan.EmbeddedLifeProductId !== null) {
                for (let i = 0; i < vm.terminateContractModel.Plans.length; i++) {
                    if (plan.EmbeddedLifeProductId === vm.terminateContractModel.Plans[i].ProductId) {
                        vm.terminateContractModel.Plans[i].Selected = plan.Selected;
                        break;
                    }
                }
            }
        }
    }
})();;
(function () {
    "use strict"

    angular
        .module("MWPApp")
        .component("terminateSubscriberConfirmationModalComponent", {
            templateUrl: "/MWP/Template/TerminateSubscriberConfirmationModal",
            controller: TerminateSubscriberConfirmationModalController,
            controllerAs: "vm",
            bindings: {
                modalInstance: "<",
                resolve: "<"
            }
        });

    TerminateSubscriberConfirmationModalController.$inject = ["TerminateSubscriberConfirmationModalService", "DataService", "ImpersonateService"];

    function TerminateSubscriberConfirmationModalController(terminateSubscriberConfirmationModalService, dataService, impersonateService) {
        let vm = this;
        vm.$onInit = init;
        vm.cancel = cancel;
        vm.submit = submit;
        vm.getCantDropPlansCombinationTranslationParams = getCantDropPlansCombinationTranslationParams;
        vm.voicePhone = dataService.PortalInfo.VoicePhone;
        vm.customerServiceEmail = dataService.PortalInfo.CustomerServiceEmail;

        function init() {
            impersonateService.getImpersonateSessionInfo()
                .then(function (response) {
                    vm.isImpersonation = response.IsImpersonation;
                });
            vm.payload = vm.resolve.payload;
            getActiveFamilyMembers();
            validatePlans();
        }
        function cancel() {
            vm.modalInstance.close(getResponse("cancel"));
        }
        function submit() {
            vm.modalInstance.close(getResponse("submit", vm.plansToTerminate));
        }
        function getResponse(result, data) {
            return { result: result, data: data };
        }

        function getActiveFamilyMembers() {
            let products = [];
            products = vm.payload.plansToTerminate.map(product => product.productId)

            terminateSubscriberConfirmationModalService.getActiveFamilyMembers(products)
                .then(function successCallback(response) {
                    if (response) {
                        vm.activeFamilyMembers = concatenateFamilyMembers(response);
                    }
                });
        }

        function concatenateFamilyMembers(activeFamilyMemberList) {
            return activeFamilyMemberList.map(function (member) { return member.FullName; }).join(", ");
        }

        function validatePlans() {
            vm.terminateSubscriberConfirmationDateError = undefined;

            terminateSubscriberConfirmationModalService.validateTerminateSubscriber(vm.payload.subscriber)
                .then(function (response) {
                    const dateReason = "date";
                    vm.plansToNotTerminate = response.data.plansToNotTerminate;
                    vm.plansToTerminate = response.data.plansToTerminate;
                    vm.terminationDate = response.data.terminationDate;
                    vm.newPrice = response.data.newPrice;
                    vm.memberIsGoingToBeBilled = response.data.memberIsGoingToBeBilled;

                    if (vm.plansToNotTerminate.length > 0) {
                        vm.plansToNotTerminateString = "";
                        for (let i = 0; i < vm.plansToNotTerminate.length; i++) {
                            if (vm.plansToNotTerminate[i].reasonToNotDrop === dateReason) {
                                vm.plansToNotTerminateString += vm.plansToNotTerminate[i].description + ", ";
                            }
                        }
                        vm.plansToNotTerminateString = vm.plansToNotTerminateString.substr(0, vm.plansToNotTerminateString.length - 2);
                        if (vm.plansToNotTerminateString !== "") {
                            vm.terminateSubscriberConfirmationDateError = {
                                Message: "EnrollmentSummary_TerminateSubscriberConfirmationModal_Exceeded_Term_Date",
                                Params: {
                                    plans: concatenatePlans(vm.plansToNotTerminate)
                                }
                            };
                        }
                    }

                    if (vm.plansToTerminate.length > 0) {
                        vm.plansToTerminateString = concatenatePlans(vm.plansToTerminate);
                    }
                });
        }

        function concatenatePlans(productList) {
            return productList.map(function (product) { return product.productName; }).join(", ");
        }

        function getCantDropPlansCombinationTranslationParams() {
            return { plans: vm.plansToNotDropCombinationString, voicePhone: vm.voicePhone, email: vm.customerServiceEmail };
        }
    }
})();;
(function () {
    'use strict';
    angular
        .module('MWPApp')
        .component('openEnrollment', {
            templateUrl: '/MWP/IndividualEnrollment/OpenEnrollmentTemplate',
            controller: openEnrollmentController,
            controllerAs: 'vm',
            bindings: {
            }
        });

    openEnrollmentController.$inject = ['OpenEnrollmentService', 'DataService', '$state', '$window', 'WbxModalService', '$timeout', '$rootScope'];
    function openEnrollmentController(openEnrollmentService, dataService, $state, $window, wbxModalService, $timeout, $rootScope) {
        var vm = this;
        const TARGET_WINDOW_SELF = "_self";
        vm.$onInit = $onInit;
        vm.goToBillingFrequency = goToBillingFrequency;
        vm.goToEnrollmentSummary = goToEnrollmentSummary;
        vm.goToAddChangePlans = goToAddChangePlans;
        vm.isOpenEnrollment = isOpenEnrollment;
        vm.getPortalInfo = getPortalInfo;
        vm.getBoldDateTranslationParams = getBoldDateTranslationParams;
        vm.getDateTranslationParams = getDateTranslationParams;
        vm.getPhoneTranslationParams = getPhoneTranslationParams;

        function $onInit() {
            vm.isIndividualEnrollmentPlanManagementEnabled = dataService.isIndividualEnrollmentPlanManagementEnabled;
            vm.isOpenEnrollment();
            vm.getPortalInfo();
        }

        function goToBillingFrequency() {
            const modalDefaults = {
                component: "updateBillingFrequencyModal",
                size: "md",
                windowClass: "",
                resolve: {}
            };
            wbxModalService.showModal(modalDefaults)
                .then(function (result) {
                    if (result !== 'close') {
                        $timeout(function () {
                            vm.successMessage = result;
                            $rootScope.$broadcast('updateBillingFrequency', true);                            
                        });
                    }
                });
        }

        function goToEnrollmentSummary() {
            var landingUrl = "https://" + $window.location.host + "/MWP/EnrollmentSummary#/summary";
            $window.open(landingUrl, TARGET_WINDOW_SELF);
        }

        function goToAddChangePlans() {
            var landingUrl = "https://" + $window.location.host + "/MWP/PlanManagement";
            $window.open(landingUrl, TARGET_WINDOW_SELF);
        }

        function isOpenEnrollment() {
            vm.isOpenEnrollmentFlag = false;
            openEnrollmentService.getIsOpenEnrollment()
                .then(function successCallback(response) {
                    if (response) {
                        vm.isOpenEnrollmentFlag = response.isOpenEnrollment;
                        if (vm.isOpenEnrollmentFlag) {
                            vm.startDate = response.startDate;
                            vm.endDate = response.endDate;
                            vm.renewDate = response.renewDate;
                        }
                    }                                                            
                },
                    function errorCallback(response) {
                        console.log("Error retrieving open enrollment information: " + response);
                    });
        };

        function getPortalInfo() {
            openEnrollmentService.getPortalInfo()
                .then(function (response) {
                    if (response) {
                        let phoneEmailTranslation = {
                            customerServicePhone: response.VoicePhone,
                            customerServiceEmail: response.CustomerServiceEmail
                        };
                        vm.portalVoicePhoneEmail = phoneEmailTranslation;
                    }
                });
        }

        function getBoldDateTranslationParams() {
            return {
                date: '<strong>' + vm.endDate + '</strong>',
                startDate: '<strong>' + vm.startDate + '</strong>',
                renewDate: '<strong>' + vm.renewDate + '</strong>'
            };
        };

        function getDateTranslationParams() {
            return { date: vm.endDate };
        };

        function getPhoneTranslationParams() {
            return vm.portalVoicePhoneEmail;
        };
    }
})();;
(function () {
    "use strict";

    angular
        .module("MWPApp")
        .component("addAuthorizeNetPaymentMethodInternalModal", {
            templateUrl: "/MWP/Template/AddAuthorizeNetPaymentMethodInternalModal",
            controller: AddAuthorizeNetPaymentMethodInternalModalController,
            controllerAs: "vm",
            bindings: {
                modalInstance: "<?",
                resolve: "<?"
            }
        });

    AddAuthorizeNetPaymentMethodInternalModalController.$inject = ["PaymentMethodService", "DataService", "$timeout", "$compile", "$scope", "$translate", "ImpersonateService"];

    function AddAuthorizeNetPaymentMethodInternalModalController(paymentMethodService, dataService, $timeout, $compile, $scope, $translate, impersonateService) {
        const ACCOUNT_TYPES_SELECT_LIST = [
            { Text: $translate.instant("PaymentMethod_AddPaymentMethod_Checking"), Value: "checking" },
            { Text: $translate.instant("PaymentMethod_AddPaymentMethod_Savings"), Value: "savings" }
        ];
        const MINIMUM_LOADING_SECONDS = 5;
        let vm = this;
        vm.paymentTypes = {
            bankAccount: "1"
        };
        vm.paymentMethodFilter = {
            PaymentTypes: [
                { Text: $translate.instant("PaymentMethod_AddPaymentMethod_DirectTransfer"), Value: vm.paymentTypes.bankAccount }
            ],
            PaymentType: vm.paymentTypes.bankAccount,
            IsPaymentTypeDisabled: false
        };
        vm.bankAccount = {
            AccountTypes: ACCOUNT_TYPES_SELECT_LIST,
        };
        vm.billingAddress = angular.copy(dataService.BillingAddressFormData);
        vm.$onInit = $onInit;
        vm.add = add;
        vm.close = close;
        vm.onPaymentTypeChange = onPaymentTypeChange;
        vm.isShowErrorMessage = isShowErrorMessage;
        vm.getAddButtonTranslationParams = getAddButtonTranslationParams;
        vm.paymentGateway = vm.resolve.paymentGateway;

        function addRoutingNumberValidation() {
            let confirmRoutingNumberinput = $("#AddBankAccountFormConfirmRoutingNumberTextBox");
            let routingNumberinput = $("#AddBankAccountFormRoutingNumberTextBox");

            routingNumberinput.attr("wbx-validate-routing-number-lenght", "");
            confirmRoutingNumberinput.attr("wbx-validate-routing-number-lenght", "");
            confirmRoutingNumberinput.attr("wbx-validate-confirm-routing-number", "");
            confirmRoutingNumberinput.attr("wbx-routing-number-value", "{{vm.bankAccount.RoutingNumber}}");
            $compile(confirmRoutingNumberinput)($scope);
            $compile(routingNumberinput)($scope);
        }

        function addAccountNumberValidation() {
            let confirmAccountNumberinput = $("#AddBankAccountFormConfirmAccountNumberTextBox");
            let accountNumberinput = $("#AddBankAccountFormAccountNumberTextBox");

            accountNumberinput.attr("wbx-account-number-mask", "");
            confirmAccountNumberinput.attr("wbx-account-number-mask", "");
            confirmAccountNumberinput.attr("wbx-validate-confirm-account-number", "");
            confirmAccountNumberinput.attr("wbx-account-number-value", "{{vm.bankAccount.AccountNumber}}");
            $compile(confirmAccountNumberinput)($scope);
            $compile(accountNumberinput)($scope);
        }

        function $onInit() {
            impersonateService.getImpersonateSessionInfo()
                .then(function (response) {
                    vm.isImpersonation = response.IsImpersonation;
                });

            $timeout(function () {
                addRoutingNumberValidation();
                addAccountNumberValidation();
            });
        }

        function add() {
            if (!vm.isImpersonation) {
                const MAX_NAME_ON_ACCOUNT_LENGTH = 22;
                vm.errorMessage = undefined;
                vm.isLoading = true;

                $timeout(function () {
                    submitForms();

                    if (!areFormsValid()) {
                        vm.errorMessage = "PaymentMethod_AddPaymentMethod_EntriesRequireAttention";
                        vm.isLoading = false;
                        return;
                    }

                    vm.errorMessage = undefined;

                    const paymentMethodData = {
                        AccountHolderName: vm.bankAccount.NameOnAccount.substring(0, MAX_NAME_ON_ACCOUNT_LENGTH).replace(/[^a-zA-Z0-9 ]/g, " "),
                        AccountName: vm.bankAccount.AccountType,
                        AccountNumber: vm.bankAccount.AccountNumber,
                        RoutingNumber: vm.bankAccount.RoutingNumber
                    };

                    paymentMethodService.addAuthorizeNetEnrolleePaymentMethodInternal(paymentMethodData)
                        .then(function (result) {
                            if (!result.IsSuccess) {
                                vm.errorMessage = result.Message;
                                vm.isLoading = false;
                                return;
                            }
                            $timeout(function () {
                                vm.modalInstance.close(result.Message);
                                vm.isLoading = false;
                            }, MINIMUM_LOADING_SECONDS * 1000);
                        });
                });
            }
        }

        function submitForms() {
            $("#AddBankAccountFormAddBankAccountFormSubmitButton").trigger("click");
            $("#BillingAddressFormBillingAddressFormSubmitButton").trigger("click");
        }

        function areFormsValid() {
            return vm.bankAccountFormName.$valid && vm.billingAddressFormName.$valid;
        }

        function close() {
            vm.modalInstance.close("close");
        }

        function onPaymentTypeChange() {
            vm.errorMessage = undefined;
            vm.bankAccount = { AccountTypes: ACCOUNT_TYPES_SELECT_LIST };
            vm.bankAccountFormName.$setPristine();
            vm.billingAddress = angular.copy(dataService.BillingAddressFormData);
            vm.billingAddressFormName.$setPristine();
        }

        function isShowErrorMessage() {
            if (vm.errorMessage === undefined) {
                return false;
            } else if (!areFormsValid()) {
                return true;
            } else {
                return false;
            }
        }

        function getAddButtonTranslationParams() {
            return {
                fullName: dataService.FullName,
            };
        }
    }
})();;
(function () {
    "use strict";

    angular
        .module("MWPApp")
        .component("addAuthorizeNetPaymentMethodModal", {
            templateUrl: "/MWP/Template/AddAuthorizeNetPaymentMethodModal",
            controller: AddAuthorizeNetPaymentMethodModalController,
            controllerAs: "vm",
            bindings: {
                modalInstance: "<?",
                resolve: "<?"
            }
        });

    AddAuthorizeNetPaymentMethodModalController.$inject = ["PaymentMethodService", "DataService", "$timeout", "$compile", "$scope", "$translate", "ImpersonateService"];

    function AddAuthorizeNetPaymentMethodModalController(paymentMethodService, dataService, $timeout, $compile, $scope, $translate, impersonateService) {
        const ACCOUNT_TYPES_SELECT_LIST = [
            { Text: $translate.instant("PaymentMethod_AddPaymentMethod_Checking"), Value: "checking" },
            { Text: $translate.instant("PaymentMethod_AddPaymentMethod_Savings"), Value: "savings" }
        ];
        const MINIMUM_LOADING_SECONDS = 5;
        let vm = this;
        vm.paymentTypes = {
            creditCard: "1",
            bankAccount: "2"
        };
        vm.paymentMethodFilter = {
            PaymentTypes: [
                { Text: $translate.instant("PaymentMethod_AddPaymentMethod_CreditCard"), Value: vm.paymentTypes.creditCard },
                { Text: $translate.instant("PaymentMethod_AddPaymentMethod_DirectTransfer"), Value: vm.paymentTypes.bankAccount }
            ],
            PaymentType: vm.paymentTypes.creditCard,
            IsPaymentTypeDisabled: false
        };
        vm.creditCard = {};
        vm.bankAccount = {
            AccountTypes: ACCOUNT_TYPES_SELECT_LIST,
        };
        vm.billingAddress = angular.copy(dataService.BillingAddressFormData);
        vm.$onInit = $onInit;
        vm.add = add;
        vm.close = close;
        vm.onPaymentTypeChange = onPaymentTypeChange;
        vm.isShowErrorMessage = isShowErrorMessage;
        vm.getAddButtonTranslationParams = getAddButtonTranslationParams;
        vm.paymentGateway = vm.resolve.paymentGateway;

        function reshapeCardNumberFields() {
            let cardNumberInputContainer = $("#AddCreditCardFormCardNumberTextBox").parent();
            $("#AddCreditCardFormExpirationDateTextBox").appendTo(cardNumberInputContainer);
            $("#AddCreditCardFormCVCTextBox").appendTo(cardNumberInputContainer);
            let validationsContainer = cardNumberInputContainer.parent().parent();
            $("#AddCreditCardFormExpirationDateTextBoxInlineValidationText").appendTo(validationsContainer);
            $("#AddCreditCardFormCVCTextBoxInlineValidationText").appendTo(validationsContainer);
            $("#AddCreditCardForm .wbx-form-column").remove();
            $("#AddCreditCardFormCardNumberTextBox").parent().attr("id", "CardNumberFieldsContainer")
        }
      
        function addCardNumberMaskAndValidation() {
            let cardNumberInput = $("#AddCreditCardFormCardNumberTextBox");
            cardNumberInput.attr("wbx-card-number-mask", "");
            $compile(cardNumberInput)($scope);
        }

        function addExpirationDateMaskAndValidation() {
            let expirationDateInput = $("#AddCreditCardFormExpirationDateTextBox");
            expirationDateInput.attr("wbx-date-mask-mmyy", "");
            expirationDateInput.attr("wbx-validate-exp-date", "");
            $compile(expirationDateInput)($scope);
        }

        function addCVCMaskAndValidation() {
            let cvcInput = $("#AddCreditCardFormCVCTextBox");
            cvcInput.attr("wbx-cvc-mask", "");
            cvcInput.attr("wbx-validate-cvc", "");
            $compile(cvcInput)($scope);
        }

        function addRoutingNumberValidation() {
            let confirmRoutingNumberinput = $("#AddBankAccountFormConfirmRoutingNumberTextBox");
            let routingNumberinput = $("#AddBankAccountFormRoutingNumberTextBox");

            routingNumberinput.attr("wbx-validate-routing-number-lenght", "");
            confirmRoutingNumberinput.attr("wbx-validate-routing-number-lenght", "");
            confirmRoutingNumberinput.attr("wbx-validate-confirm-routing-number", "");
            confirmRoutingNumberinput.attr("wbx-routing-number-value", "{{vm.bankAccount.RoutingNumber}}");
            $compile(confirmRoutingNumberinput)($scope);
            $compile(routingNumberinput)($scope);
        }

        function addAccountNumberValidation() {
            let confirmAccountNumberinput = $("#AddBankAccountFormConfirmAccountNumberTextBox");
            let accountNumberinput = $("#AddBankAccountFormAccountNumberTextBox");

            accountNumberinput.attr("wbx-account-number-mask", "");
            confirmAccountNumberinput.attr("wbx-account-number-mask", "");
            confirmAccountNumberinput.attr("wbx-validate-confirm-account-number", "");
            confirmAccountNumberinput.attr("wbx-account-number-value", "{{vm.bankAccount.AccountNumber}}");
            $compile(confirmAccountNumberinput)($scope);
            $compile(accountNumberinput)($scope);
        }
      
        function $onInit() {
            impersonateService.getImpersonateSessionInfo()
                .then(function (response) {
                    vm.isImpersonation = response.IsImpersonation;
                });

            $timeout(function () {
                reshapeCardNumberFields();
                addCardNumberMaskAndValidation();
                addExpirationDateMaskAndValidation();
                addCVCMaskAndValidation();
                addRoutingNumberValidation();
                addAccountNumberValidation();
            });
        }

        function add() {
            if (!vm.isImpersonation) {
                const MAX_NAME_ON_CARD_LENGTH = 64;
                const MAX_NAME_ON_ACCOUNT_LENGTH = 22;
                vm.errorMessage = undefined;
                vm.isLoading = true;
                
                $timeout(function () {
                    submitForms();

                    if (!areFormsValid()) {
                        vm.errorMessage = "PaymentMethod_AddPaymentMethod_EntriesRequireAttention";
                        vm.isLoading = false;
                        return;
                    }

                    vm.errorMessage = undefined;
                    paymentMethodService.getEnrolleePaymentGateway()
                        .then(function (response) {
                            let secureData = {
                                authData: {
                                    clientKey: response.publicClientKey,
                                    apiLoginID: response.publicKey
                                }
                            };

                            let customerData = {
                                paymentGatewayId: response.paymentGatewayId
                            };

                            if (vm.paymentMethodFilter.PaymentType == vm.paymentTypes.creditCard) {
                                customerData.paymentType = "CreditCard";
                                customerData.name = vm.creditCard.NameOnCard;
                                secureData.cardData = {
                                    cardNumber: vm.creditCard.CardNumber.replace(/\s+/g, ""),
                                    month: vm.creditCard.ExpirationDate.split("/")[0],
                                    year: vm.creditCard.ExpirationDate.split("/")[1],
                                    cardCode: vm.creditCard.CVC,
                                    zip: vm.billingAddress.ZipCode,
                                    fullName: vm.creditCard.NameOnCard.substring(0, MAX_NAME_ON_CARD_LENGTH)
                                };
                            } else if (vm.paymentMethodFilter.PaymentType == vm.paymentTypes.bankAccount) {
                                customerData.paymentType = "ACH";
                                customerData.name = vm.bankAccount.NameOnAccount;
                                secureData.bankData = {
                                    accountNumber: vm.bankAccount.AccountNumber,
                                    routingNumber: vm.bankAccount.RoutingNumber,
                                    nameOnAccount: vm.bankAccount.NameOnAccount.substring(0, MAX_NAME_ON_ACCOUNT_LENGTH).replace(/[^a-zA-Z0-9 ]/g, " "),
                                    accountType: vm.bankAccount.AccountType
                                };
                            }

                            registerPaymentMethod(secureData, customerData);
                        });
                });
            }
        }
        function registerPaymentMethod(secureData, customerData) {
            let responseCount = 0;

            Accept.dispatchData(secureData, function (response) {
                if (responseCount > 0) {
                    return;
                }

                responseCount++;

                if (response.messages.resultCode === "Error") {
                    vm.errorMessage = "";
                    let i = 0;

                    while (i < response.messages.message.length) {
                        vm.errorMessage += " " + response.messages.message[i].text + "\r\n";
                        i = i + 1;
                    }
                    
                    vm.isLoading = false;
                } else {
                    let paymentMethodData = {
                        paymentGatewayId: customerData.paymentGatewayId,
                        encryptedPaymentInfo: response.opaqueData.dataValue,
                        name: customerData.name,
                        email: vm.billingAddress.Email,
                        paymentType: customerData.paymentType
                    };
                    associatePaymentMethodToEnrollee(paymentMethodData);
                }
            });
        }
      
        function associatePaymentMethodToEnrollee(paymentMethodData) {
            paymentMethodService.addAuthorizeNetEnrolleePaymentMethod(paymentMethodData)
                .then(function (result) {
                    if (!result.IsSuccess) {
                        vm.errorMessage = result.Message;
                        vm.isLoading = false;
                        return;
                    }
                    $timeout(function () {
                        vm.modalInstance.close(result.Message);
                        vm.isLoading = false;
                    }, MINIMUM_LOADING_SECONDS * 1000);
                });
        }

        function submitForms() {
            if (vm.paymentMethodFilter.PaymentType == vm.paymentTypes.creditCard) {
                $("#AddCreditCardFormAddCreditCardFormSubmitButton").trigger("click");
            } else if (vm.paymentMethodFilter.PaymentType == vm.paymentTypes.bankAccount) {
                $("#AddBankAccountFormAddBankAccountFormSubmitButton").trigger("click");
            }
            $("#BillingAddressFormBillingAddressFormSubmitButton").trigger("click");
        }

        function areFormsValid() {
            return (vm.paymentMethodFilter.PaymentType != vm.paymentTypes.creditCard || vm.creditCardFormName.$valid) &&
                (vm.paymentMethodFilter.PaymentType != vm.paymentTypes.bankAccount || vm.bankAccountFormName.$valid) &&
                vm.billingAddressFormName.$valid;
        }

        function close() {
            vm.modalInstance.close("close");
        }

        function onPaymentTypeChange() {
            vm.errorMessage = undefined;
            vm.creditCard = {};
            vm.creditCardFormName.$setPristine();
            vm.bankAccount = { AccountTypes: ACCOUNT_TYPES_SELECT_LIST };
            vm.bankAccountFormName.$setPristine();
            vm.billingAddress = angular.copy(dataService.BillingAddressFormData);
            vm.billingAddressFormName.$setPristine();
        }

        function isShowErrorMessage() {
            if (vm.errorMessage === undefined) {
                return false;
            } else if (!areFormsValid()) {
                return true;
            } else {
                return false;
            }
        }

        function getAddButtonTranslationParams() {
            return {
                fullName: dataService.FullName,
            };
        }
    }
})();
;
/** @typedef {{ text: string, value: string}} PaymentMethod */
/** @typedef {('Stripe'|'AuthorizeNet'|'StripeAchNoVerify')} PaymentGatewayType */
/** @typedef {{publicKey: string, paymentGatewayId: number, gateway: string, publicKey: string, publicClientKey: string, paymentMethods: PaymentMethod[], paymentGatewayType: PaymentGatewayType}} PaymentGateway */

(function () {
    "use strict";

    angular.module("MWPApp").component("addStripePaymentMethodModal", {
        templateUrl: "/MWP/Template/AddStripePaymentMethodModal",
        controller: AddStripePaymentMethodModalController,
        controllerAs: "vm",
        bindings: {
            modalInstance: "<?",
            resolve: "<?",
        },
    });

    AddStripePaymentMethodModalController.$inject = [
        "PaymentMethodService",
        "DataService",
        "$timeout",
        "$q",
        "$translate",
        "ImpersonateService",
        "$scope",
    ];

    const MINIMUM_LOADING_SECONDS = 5;

    const PaymentMethods = {
        CreditCard: { text: "CreditCard", value: "3" },
        ACH: { text: "ACH", value: "6" },
    };

    function AddStripePaymentMethodModalController(
        paymentMethodService,
        dataService,
        $timeout,
        $q,
        $translate,
        impersonateService,
        $scope,
    ) {
        const ACCOUNT_TYPES_SELECT_LIST = [
            {
                Text: $translate.instant("PaymentMethod_AddPaymentMethod_Checking"),
                Value: "checking",
            },
            {
                Text: $translate.instant("PaymentMethod_AddPaymentMethod_Savings"),
                Value: "savings",
            },
        ];

        const vm = this;

        vm.paymentTypes = {
            creditCard: "1",
            bankAccount: "2",
        };
        vm.paymentMethodFilter = {
            PaymentTypes: [
                {
                    Text: $translate.instant("PaymentMethod_AddPaymentMethod_CreditCard"),
                    Value: vm.paymentTypes.creditCard,
                },
                {
                    Text: $translate.instant(
                        "PaymentMethod_AddPaymentMethod_DirectTransfer"
                    ),
                    Value: vm.paymentTypes.bankAccount,
                },
            ],
            PaymentType: vm.paymentTypes.creditCard,
            IsPaymentTypeDisabled: false,
        };

        vm.paymentType = PaymentMethods.CreditCard.text;
        vm.bankAccount = {
            AccountTypes: ACCOUNT_TYPES_SELECT_LIST,
        };
        vm.billingAddress = angular.copy(dataService.BillingAddressFormData);
        vm.billingAddress.IsCreditCardPaymentMethod = true;
        vm.billingAddress.IsACHPaymentMethod = false;
        vm.$onInit = $onInit;
        vm.onAdd = onAdd;
        vm.onNameChange = onNameChange;
        vm.onClose = onClose;
        vm.onPaymentTypeChange = onPaymentTypeChange;
        vm.isShowErrorMessage = isShowErrorMessage;
        vm.getAddButtonTranslationParams = getAddButtonTranslationParams;

        /**
         * @type {PaymentGateway}
         */
        vm.paymentGateway = dataService.PaymentGateway;

        function createOrUpdateAndMountPaymentElement(
            elements,
            hostElement,
            onChange,
            onReady
        ) {
            const paymentElementOptions = {
                fields: {
                    billingDetails: {
                        name: "never",
                        address: {
                            city: "never",
                            state: "never",
                            line1: "never",
                            line2: "never",
                            postalCode: "never",
                            country: "never",
                        },
                        email: "never",
                        phone: "never",
                    },
                },
                wallets: {
                    googlePay: "never",
                    applePay: "never",
                },
                layout: {
                    radios: false,
                    type: "accordion",
                },
            };

            const paymentElement = elements.getElement("payment")
                ? elements.getElement("payment")
                : elements.create("payment", paymentElementOptions);

            paymentElement.mount(hostElement);
            paymentElement.on("change", onChange);
            paymentElement.on("ready", onReady);
            paymentElement.on("loaderror", onReady);

            return paymentElement;
        }

        function $onInit() {
            impersonateService.getImpersonateSessionInfo().then(function (response) {
                vm.isImpersonation = response.IsImpersonation;
            });

            $timeout(function () {
                const setup = function () {
                    const hostElement = angular.element("#payment-element")[0];

                    createOrUpdateAndMountPaymentElement(
                        vm.resolve.elements,
                        hostElement,
                        ($event) => {
                            onPaymentTypeChange($event);
                        },
                        () => {}
                    );
                };

                setup();
            });
        }

        function onClose() {
            vm.modalInstance.close("close");
        }

        function onAdd() {
            vm.errorMessage = undefined;
            vm.isLoading = true;

            $timeout(function () {
                submitForms();

                if (!areFormsValid()) {
                    vm.errorMessage =
                        "PaymentMethod_AddPaymentMethod_EntriesRequireAttention";
                    vm.isLoading = false;
                    return;
                }

                registerPaymentMethod();
            });
        }

        function submitForms() {
            $("#BillingAddressFormBillingAddressFormSubmitButton").trigger("click");
        }

        /**
         * @param {'CreditCard' | 'ACH'} source 
         */
        function onNameChange(source) {
            if (source === PaymentMethods.CreditCard.text) {
                vm.billingAddress.NameOnAccount = vm.billingAddress.NameOnCard;
                
            } else if (source === PaymentMethods.ACH.text) {
                vm.billingAddress.NameOnCard = vm.billingAddress.NameOnAccount;
            }            
        }

        function registerPaymentMethod() {
            const elements = vm.resolve.elements;
            const stripe = vm.resolve.Stripe;

            const toBillingDetails = (form, email, phone) => {
                return {
                    name: vm.paymentType === PaymentMethods.CreditCard.text ? form.NameOnCard : form.NameOnAccount,
                    address: {
                        line1: form.Address1,
                        line2: form.Address2,
                        city: form.City,
                        state: form.State,
                        postal_code: form.ZipCode,
                        country: "US",
                    },
                    email,
                    phone,
                };
            };

            const billingDetails = toBillingDetails(
                vm.billingAddress,
                dataService.Email,
                dataService.Phone
            );

            stripe
                .confirmSetup({
                    elements,
                    confirmParams: {
                        payment_method_data: {
                            billing_details: billingDetails,
                        },
                    },
                    redirect: "if_required",
                })
                .then((response) => {
                    let paymentMethodId;

                    if (response.setupIntent) {
                        paymentMethodId = response.setupIntent.payment_method;
                    }

                    if (typeof paymentMethodId !== "string") {
                        vm.isLoading = false;
                        if (response.error && response.error.message) {
                            return $q.reject(response.error.message);
                        }

                        return $q.reject(
                            "An unknown error occured. Please try again later"
                        );
                    }

                    vm.errorMessage = undefined;
                    associatePaymentMethodToEnrollee(paymentMethodId);
                })
                .catch((error) => {
                    vm.isLoading = false;
                    vm.errorMessage = error;
                });
        }

        /**
         *
         * @param {number} paymentGatewayPaymentMethodId
         */
        function associatePaymentMethodToEnrollee(
            paymentGatewayPaymentMethodId
        ) {
            const { paymentGatewayId } = vm.paymentGateway;

            const paymentMethodData = {
                paymentMethod: vm.paymentType,
                paymentGatewayId,
                paymentGatewayPaymentMethodId,
                paymentGatewayCustomerId: vm.resolve.paymentGatewayCustomerId,
            };

            paymentMethodService
                .addStripeEnrolleePaymentMethod(paymentMethodData)
                .then(function (result) {
                    if (!result.IsSuccess) {
                        vm.errorMessage = result.Message;
                        vm.isLoading = false;
                        return;
                    }

                    $timeout(function () {
                        vm.modalInstance.close(result.Message);
                        vm.isLoading = false;
                    }, MINIMUM_LOADING_SECONDS * 1000);
                });
        }

        function areFormsValid() {
            return vm.billingAddressFormName.$valid;
        }

        /**
         *
         * @param {{ value: { type: 'card' | 'us_bank_account' }}} $event
         */
        function onPaymentTypeChange($event) {
            vm.paymentType =
                $event.value.type === "card"
                    ? PaymentMethods.CreditCard.text
                    : PaymentMethods.ACH.text;
            vm.billingAddress.IsCreditCardPaymentMethod = vm.paymentType === PaymentMethods.CreditCard.text;
            vm.billingAddress.IsACHPaymentMethod = !vm.billingAddress.IsCreditCardPaymentMethod;
            vm.errorMessage = undefined;

            $scope.$apply();
        }

        function isShowErrorMessage() {
            if (vm.errorMessage === undefined) {
                return false;
            } else if (!areFormsValid()) {
                return true;
            } else {
                return false;
            }
        }

        function getAddButtonTranslationParams() {
            return {
                fullName: dataService.FullName,
            };
        }
    }
})();
;
(function () {
    "use strict";
    angular
        .module("MWPApp")
        .component("deletePaymentMethodModal", {
            controller: deletePaymentMethodModal,
            controllerAs: "vm",
            templateUrl: "/MWP/Template/DeletePaymentMethodModal",
            bindings: {
                modalInstance: "<"
            }
        })

    deletePaymentMethodModal.$inject = ["ImpersonateService"];

    function deletePaymentMethodModal(impersonateService) {
        let vm = this;

        vm.cancel = cancel;
        vm.submit = submit;
        vm.$onInit = $onInit;

        function $onInit() {
            impersonateService.getImpersonateSessionInfo()
                .then(function (response) {
                    vm.isImpersonation = response.IsImpersonation;
                });
        }

        function cancel() {
            vm.modalInstance.close("close");
        }

        function submit() {
            vm.modalInstance.close(true);
        }
    }
})();;
(function () {
    "use strict";

    angular
        .module("MWPApp")
        .component("updatePaymentMethodInternalModal", {
            templateUrl: "/MWP/Template/UpdatePaymentMethodInternalModal",
            controller: UpdatePaymentMethodInternalModalController,
            controllerAs: "vm",
            bindings: {
                modalInstance: "<",
                resolve: "<"
            }
        });

    UpdatePaymentMethodInternalModalController.$inject = ["PaymentMethodService", "DataService", "$timeout", "WbxModalService", "ImpersonateService"];

    function UpdatePaymentMethodInternalModalController(paymentMethodService, dataService, $timeout, wbxModalService, impersonateService) {
        const MINIMUM_LOADING_SECONDS = 5;
        const SUCCESS_MESSAGE = "PaymentMethod_AddPaymentMethod_UpdatePaymentSuccessMessage";
        const UPDATING_MESSAGE = "PaymentMethod_AddPaymentMethod_UpdatingMessage";
        let vm = this;

        vm.$onInit = $onInit;
        vm.close = close;
        vm.selectActivePaymentMethod = selectActivePaymentMethod;
        vm.promptAddPaymentMethodModal = promptAddPaymentMethodModal;
        vm.promptDeleteEnrolleePaymentMethod = promptDeleteEnrolleePaymentMethod;
        vm.deletePaymentMethodTooltip = deletePaymentMethodTooltip;
        vm.getAddPaymentMethodButtonTranslationParams = getAddPaymentMethodButtonTranslationParams;

        function $onInit() {
            impersonateService.getImpersonateSessionInfo()
                .then(function (response) {
                    vm.isImpersonation = response.IsImpersonation;
                });

            getAllEnrolleePaymentMethods();
        }

        function getAllEnrolleePaymentMethods(message = "") {
            paymentMethodService
                .getAllEnrolleePaymentMethods()
                .then(function (response) {
                    vm.paymentMethods = response.data;
                    vm.paymentMethods.forEach((paymentMethod) => {
                        paymentMethod.isTopList = paymentMethod.activeFlag;
                    });
                    if (message) {
                        vm.successMessage = message;
                    }
                });
        }

        function close() {
            vm.modalInstance.close("close");
        }

        function selectActivePaymentMethod(enrolleePaymentMethodId) {
            vm.alertProcessing = UPDATING_MESSAGE;
            updateActiveFlag(enrolleePaymentMethodId);
            updateEnrolleePaymentMethod(enrolleePaymentMethodId);
        }

        function updateEnrolleePaymentMethod(enrolleePaymentMethodId) {
            paymentMethodService
                .updateEnrolleePaymentMethod(enrolleePaymentMethodId)
                .then(function (response) {
                    if (!response.IsSuccess) {
                        vm.errorMessage = response.Message;
                        getAllEnrolleePaymentMethods();
                        vm.alertProcessing = undefined;
                        return;
                    }

                    $timeout(function () {
                        vm.alertProcessing = undefined;
                        vm.errorMessage = undefined;
                        vm.successMessage = SUCCESS_MESSAGE;

                        vm.paymentMethods.find(
                            (x) => x.enrolleePaymentMethodId === enrolleePaymentMethodId
                        ).isTopList = true;
                    }, MINIMUM_LOADING_SECONDS * 1000);
                })
                .catch(function () {
                    vm.alertProcessing = undefined;
                    getAllEnrolleePaymentMethods();
                });
        }

        function updateActiveFlag(enrolleePaymentMethodId) {
            angular.forEach(vm.paymentMethods, function (paymentMethod) {
                paymentMethod.activeFlag =
                    paymentMethod.enrolleePaymentMethodId === enrolleePaymentMethodId;
                paymentMethod.isTopList = false;
            });
        }

        function promptAddPaymentMethodModal() {
            const component = "addAuthorizeNetPaymentMethodInternalModal";

            const modalDefaults = {
                component,
                size: "md",
                windowClass: "",
                resolve: {
                    elements: function () {
                        return vm.resolve.elements;
                    },
                    paymentGatewayCustomerId: function () {
                        return vm.resolve.paymentGatewayCustomerId;
                    },
                },
            };

            wbxModalService.showModal(modalDefaults).then(function (result) {
                if (result !== "close") {
                    vm.errorMessage = undefined;
                    getAllEnrolleePaymentMethods();
                }
            });
        }

        function promptDeleteEnrolleePaymentMethod(enrolleePaymentMethodId) {
            const modalDefaults = {
                component: "deletePaymentMethodModal",
                size: "sm",
                windowClass: "",
                resolve: {},
            };
            wbxModalService.showModal(modalDefaults).then(function (response) {
                if (response !== "close") {
                    deleteEnrolleePaymentMethod(enrolleePaymentMethodId);
                }
            });
        }

        function deleteEnrolleePaymentMethod(enrolleePaymentMethodId) {
            paymentMethodService
                .deleteEnrolleePaymentMethod(enrolleePaymentMethodId)
                .then(function (response) {
                    if (!response.IsSuccess) {
                        vm.errorMessage = response.Message;
                        return;
                    }

                    vm.errorMessage = undefined;
                    vm.successMessage = response.Message;
                    getAllEnrolleePaymentMethods();
                });
        }

        function deletePaymentMethodTooltip(activeFlag) {
            return activeFlag
                ? "PaymentMethod_UpdatePaymentMethod_CannotDeleteActiveMethodMessage"
                : "";
        }

        function getAddPaymentMethodButtonTranslationParams() {
            return {
                fullName: dataService.FullName,
            };
        }
    }
})();
;
(function () {
    "use strict";

    angular
        .module("MWPApp")
        .component("updatePaymentMethodModal", {
            templateUrl: "/MWP/Template/UpdatePaymentMethodModal",
            controller: UpdatePaymentMethodModalController,
            controllerAs: "vm",
            bindings: {
                modalInstance: "<",
                resolve: "<"
            }
        });

    UpdatePaymentMethodModalController.$inject = ["PaymentMethodService", "DataService", "$timeout", "WbxModalService", "ImpersonateService"];

    function UpdatePaymentMethodModalController(paymentMethodService, dataService, $timeout, wbxModalService, impersonateService) {
        const MINIMUM_LOADING_SECONDS = 5;
        const SUCCESS_MESSAGE = "PaymentMethod_AddPaymentMethod_UpdatePaymentSuccessMessage";
        const SELECT_PAYMENT_MESSAGE = "PaymentMethod_AddPaymentMethod_SelectPaymentMessage";
        const UPDATING_MESSAGE = "PaymentMethod_AddPaymentMethod_UpdatingMessage";
        const PAYMENT_GATEWAY_NOT_CONFIGURED_MESSAGE = "PaymentMethod_AddPaymentMethod_PaymentGatewayNotConfiguredMessage";

        let vm = this;
        vm.paymentMethodsType = {
            creditCard: "CreditCard",
            ach: "ACH"
        };
        vm.isAddPaymentMethodDisabled = true;
        vm.addPaymentMethodDisabledTooltip = undefined;

        vm.$onInit = $onInit;
        vm.close = close;
        vm.selectActivePaymentMethod = selectActivePaymentMethod;
        vm.getColorForExpirationDate = getColorForExpirationDate;
        vm.isExpired = isExpired;
        vm.promptAddPaymentMethodModal = promptAddPaymentMethodModal;
        vm.promptDeleteEnrolleePaymentMethod = promptDeleteEnrolleePaymentMethod;
        vm.deletePaymentMethodTooltip = deletePaymentMethodTooltip;
        vm.getAddPaymentMethodButtonTranslationParams = getAddPaymentMethodButtonTranslationParams;

        function $onInit() {
            impersonateService.getImpersonateSessionInfo()
                .then(function (response) {
                    vm.isImpersonation = response.IsImpersonation;
                });

            getAllEnrolleePaymentMethods();
            checkPaymentGateway();
        }

        function getAllEnrolleePaymentMethods(message = "") {
            paymentMethodService
                .getAllEnrolleePaymentMethods()
                .then(function (response) {
                    vm.paymentMethods = response.data;
                    vm.paymentMethods.forEach((paymentMethod) => {
                        paymentMethod.isExpired = isExpired(paymentMethod.creditCardExpirationDate);
                        verifyExpiredActivePaymentMethod(paymentMethod.activeFlag, paymentMethod.creditCardExpirationDate);
                        paymentMethod.isTopList = paymentMethod.activeFlag;
                    });
                    if (message) {
                        vm.successMessage = message;
                    }
                });
        }

        function checkPaymentGateway() {
            vm.isAddPaymentMethodDisabled = dataService.PaymentGateway == undefined;
            vm.addPaymentMethodDisabledTooltip = vm.isAddPaymentMethodDisabled ? PAYMENT_GATEWAY_NOT_CONFIGURED_MESSAGE : undefined;
            vm.warningMessage = vm.isAddPaymentMethodDisabled ? PAYMENT_GATEWAY_NOT_CONFIGURED_MESSAGE : undefined;
        }

        function close() {
            vm.modalInstance.close("close");
        }

        function getColorForExpirationDate(expirationDate) {
            if (isExpired(expirationDate)) {
                return "wbx-danger-color";
            } else {
                return undefined;
            }
        }

        function isExpired(expirationDate) {
            if (expirationDate === null || expirationDate === undefined) {
                return false;
            }

            let currentDate = new Date();
            let expirationDateFormat = new Date(expirationDate);
            expirationDateFormat.setMonth(expirationDateFormat.getMonth() + 1);
            expirationDateFormat = new Date(expirationDateFormat.getFullYear(), expirationDateFormat.getMonth(), 1);

            return expirationDateFormat < currentDate;
        }

        function verifyExpiredActivePaymentMethod(activeFlag, expirationDate) {
            if (isExpired(expirationDate) && activeFlag && vm.errorMessage === undefined) {
                vm.errorMessage = SELECT_PAYMENT_MESSAGE;
            }
        }

        function selectActivePaymentMethod(enrolleePaymentMethodId) {
            vm.alertProcessing = UPDATING_MESSAGE;
            updateActiveFlag(enrolleePaymentMethodId);
            updateEnrolleePaymentMethod(enrolleePaymentMethodId);
        }

        function updateEnrolleePaymentMethod(enrolleePaymentMethodId) {
            paymentMethodService
                .updateEnrolleePaymentMethod(enrolleePaymentMethodId)
                .then(function (response) {
                    if (!response.IsSuccess) {
                        vm.errorMessage = response.Message;
                        getAllEnrolleePaymentMethods();
                        vm.alertProcessing = undefined;
                        return;
                    }

                    $timeout(function () {
                        vm.alertProcessing = undefined;
                        vm.errorMessage = undefined;
                        vm.successMessage = SUCCESS_MESSAGE;

                        vm.paymentMethods.find(
                            (x) => x.enrolleePaymentMethodId === enrolleePaymentMethodId
                        ).isTopList = true;
                    }, MINIMUM_LOADING_SECONDS * 1000);
                })
                .catch(function () {
                    vm.alertProcessing = undefined;
                    getAllEnrolleePaymentMethods();
                });
        }

        function updateActiveFlag(enrolleePaymentMethodId) {
            angular.forEach(vm.paymentMethods, function (paymentMethod) {
                paymentMethod.activeFlag =
                    paymentMethod.enrolleePaymentMethodId === enrolleePaymentMethodId;
                paymentMethod.isTopList = false;
            });
        }

        function promptAddPaymentMethodModal() {
            if (vm.isAddPaymentMethodDisabled) {
                return;
            }

            const component =
                (dataService.PaymentGateway.paymentGatewayType === "Stripe" || 
                 dataService.PaymentGateway.paymentGatewayType === "StripeAchNoVerify")
                    ? "addStripePaymentMethodModal"
                    : "addAuthorizeNetPaymentMethodModal";

            const modalDefaults = {
                component,
                size: "md",
                windowClass: "",
                resolve: {
                    elements: function () {
                        return vm.resolve.elements;
                    },
                    Stripe: function () {
                        return vm.resolve.Stripe;
                    },
                    paymentGatewayCustomerId: function () {
                        return vm.resolve.paymentGatewayCustomerId;
                    },
                },
            };

            wbxModalService.showModal(modalDefaults).then(function (result) {
                if (result !== "close") {
                    vm.errorMessage = undefined;
                    getAllEnrolleePaymentMethods();

                    if (dataService.PaymentGateway.paymentGatewayType === "Stripe" || 
                        dataService.PaymentGateway.paymentGatewayType === "StripeAchNoVerify") {
                        paymentMethodService.createSetupIntent(
                            dataService.PaymentGateway.paymentGatewayId,
                            vm.resolve.paymentGatewayCustomerId
                        ).then((response) => {
                            vm.resolve.elements = vm.resolve.Stripe.elements({
                                clientSecret: response.PaymentGatewayPreAuthToken,
                                appearance: {
                                    variables: {
                                        fontWeightNormal: "400",
                                        fontFamily: '"ui-sans-serif", system-ui, -apple-system',
                                        fontSizeBase: "14px",
                                        colorTextPlaceholder: "#CFD7E0",
                                    },
                                    theme: "stripe",
                                },
                                loader: "always",
                            });
                        });
                    }
                }
            });
        }

        function promptDeleteEnrolleePaymentMethod(enrolleePaymentMethodId) {
            const modalDefaults = {
                component: "deletePaymentMethodModal",
                size: "sm",
                windowClass: "",
                resolve: {},
            };
            wbxModalService.showModal(modalDefaults).then(function (response) {
                if (response !== "close") {
                    deleteEnrolleePaymentMethod(enrolleePaymentMethodId);
                }
            });
        }

        function deleteEnrolleePaymentMethod(enrolleePaymentMethodId) {
            paymentMethodService
                .deleteEnrolleePaymentMethod(enrolleePaymentMethodId)
                .then(function (response) {
                    if (!response.IsSuccess) {
                        vm.errorMessage = response.Message;
                        return;
                    }

                    vm.errorMessage = undefined;
                    vm.successMessage = response.Message;
                    getAllEnrolleePaymentMethods();
                });
        }

        function deletePaymentMethodTooltip(activeFlag) {
            return activeFlag
                ? "PaymentMethod_UpdatePaymentMethod_CannotDeleteActiveMethodMessage"
                : "";
        }

        function getAddPaymentMethodButtonTranslationParams() {
            return {
                fullName: dataService.FullName,
            };
        }
    }
})();;
(function () {
    'use strict'

    angular
        .module('MWPApp')
        .component('addDependentConfirmationModalComponent', {
            templateUrl: '/MWP/EnrollmentSummary/AddDependentConfirmationModal',
            controller: AddDependentConfirmationModalController,
            controllerAs: 'vm',
            bindings: {
                modalInstance: '<',
                resolve: '<'
            }
        });

    AddDependentConfirmationModalController.$inject = ['AddDependentConfirmationModalService', 'EnrollmentSummaryService', 'DataService', 'ImpersonateService'];

    function AddDependentConfirmationModalController(addDependentConfirmationModalService, enrollmentSummaryService, dataService, impersonateService) {
        var vm = this;
        vm.$onInit = init;
        vm.cancel = cancel;
        vm.submit = submit;
        vm.getCantDropPlansCombinationTranslationParams = getCantDropPlansCombinationTranslationParams;
        vm.addDependentBillingFrequencyError = undefined;
        const MONTHLY_BILLING_CYCLE_TYPE = 1;
        const RENEWAL_PERIOD_CHANGE_ADD_REASON_CODE = 8;

        function init() {
            impersonateService.getImpersonateSessionInfo()
                .then(function (response) {
                    vm.isImpersonation = response.IsImpersonation;
                });

            vm.payload = vm.resolve.payload;
            vm.voicePhone = dataService.PortalInfo.VoicePhone;
            vm.customerServiceEmail = dataService.PortalInfo.CustomerServiceEmail;
            validatePlans();
        }
        function cancel() {
            vm.modalInstance.close(getResponse('cancel'));
        }
        function submit() {
            validateBillingCycle(function (response) {
                if (response.isAnnualContract === true && response.isOpenEnrollment === false) return;
                vm.modalInstance.close(getResponse('submit', vm.plansToAdd));
            });
        }
        function validateBillingCycle(callback) {
            enrollmentSummaryService.isCurrentDateAfter19thOfTheLastMonthFromCurrentContract({
                isOpenEnrollment: vm.payload.isOpenEnrollment, qualifyingEvent: vm.payload.addReasonCode === undefined ? null : vm.payload.addReasonCode, effectiveDate: vm.payload.effectiveDate })
                .then(function (response) {
                    vm.isCurrentDateAfter19thOfTheLastMonthFromCurrentContract = response;
                    vm.billingCycleType = response.billingCycleType;
                    vm.billingCycleTypeName = response.billingCycleTypeDescription;
                    if (vm.billingCycleType !== MONTHLY_BILLING_CYCLE_TYPE && vm.payload.addReasonCode != RENEWAL_PERIOD_CHANGE_ADD_REASON_CODE) {
                        vm.addDependentBillingFrequencyError = {
                            Message: 'AddDependents_BillingFrequencyValidation_Unable_Add_Dependents',
                            Params: {
                                billingFrequency: vm.billingCycleTypeName,
                                customerServicePhone: vm.voicePhone,
                                customerServiceEmail: vm.customerServiceEmail
                            }
                        };
                        return;
                    }
                    callback({ isAnnualContract: vm.isCurrentDateAfter19thOfTheLastMonthFromCurrentContract.isAnnualContract, isOpenEnrollment: vm.payload.isOpenEnrollment });
                });
        }
        function validatePlans() {
            var inputValidate = {
                eventDate: vm.payload.addReasonEventDate,
                isFutureEligibility: vm.payload.isFutureEligibility,
                subscriberEffectiveDate: vm.payload.subscriberEffectiveDate,
                plans: vm.payload.products,
                addReasonCode: vm.payload.addReasonCode,
                isOpenEnrollment: vm.payload.isOpenEnrollmentFlag,
                billingCycle: dataService.billingCycleType,
                premiumGroupId: dataService.GroupId,
                enrolleeType: vm.payload.relationshipCode
            };

            addDependentConfirmationModalService.validateAddDependent(inputValidate)
                .then(function (result) {
                    vm.payload.effectiveDate = result.data.EffectiveDate;
                    vm.plansToAdd = result.data.PlansToAdd;
                    vm.plansToAddString = concatenate(vm.plansToAdd);
                    vm.newPrice = result.data.NewPrice;

                    if (result.data.PlansCantAddDate.length > 0) {
                        vm.addDependentConfirmationDateError = {
                            Message: 'AddDependentConfirmationModal_TerminationDateError',
                            Params: {
                                plansCantAddDate: concatenate(result.data.PlansCantAddDate)
                            }
                        };
                    }

                    if (result.data.PlansCantAddDependent.length > 0) {
                        vm.addDependentConfirmationCombinationError = {
                            Message: 'AddDependentConfirmationModal_DependentCombinationError',
                            Params: {
                                plansCantAddDependent: concatenate(result.data.PlansCantAddDependent),
                                phone: vm.voicePhone,
                                email: vm.customerServiceEmail
                            }
                        };
                    }
                });
        }
        function getResponse(result, data) {
            return { result: result, data: data };
        }
        function concatenate(productList) {
            return productList.map(function (product) { return product.productDescription; }).join(", ");
        }
        function getCantDropPlansCombinationTranslationParams() {
            return { plans: vm.plansToNotDropCombinationString, customerServicePhone: vm.voicePhone, customerServiceEmail: vm.customerServiceEmail };
        }
    }
})();;
(function () {
    'use strict';
    angular
        .module('MWPApp')
        .component('addEnrollmentSummary', {
            templateUrl: 'addEnrollmentSummaryTemplate',
            controller: addEnrollmentSummaryController,
            controllerAs: 'vm',
            bindings: {
                previousState: '<'
            }
        });

    addEnrollmentSummaryController.$inject = ['DataService', 'EnrollmentSummaryService', 'OpenEnrollmentService', '$state', '$stateParams', 'enrollmentSummaryModes', 'wbxListErrorsService', 'WbxModalService'];
    function addEnrollmentSummaryController(DataService, enrollmentSummaryService, openEnrollmentService, $state, $stateParams, enrollmentSummaryModes, wbxListErrorsService, wbxModalService) {
        const RELATIONSHIP_CODE_CHILD = "19";
        const RELATIONSHIP_CODE_SPOUSE = "01";
        const DEPENDENT_TYPE_SPOUSE = "spouse";
        const ACTIVE_DEPENDENT_CODE = 1;
        const QUALIFYING_EVENT_TYPE = "Add dependent";
        const RENEWAL_PERIOD_CHANGE_ADD_REASON_CODE = 8;
        const MONTHLY_BILLING_CYCLE_TYPE = 1;

        var vm = this;
        vm.step = 1;
        vm.isSpouse = isSpouse;
        vm.dependentAgeCutoff = DataService.DependentAgeCutoff ? DataService.DependentAgeCutoff : undefined;
        vm.addData = {};
        vm.qualifyingEventType = QUALIFYING_EVENT_TYPE;
        vm.renewalPeriodChangeAddReasonCode = RENEWAL_PERIOD_CHANGE_ADD_REASON_CODE;
        vm.documents = [];
        vm.editDependentIndex = null;
        vm.genderList = [
            {
                VALUE: 'F',
                DESCRIPTION: "{{'EnrollmentSummary_Female' | translate}}"
            },
            {
                VALUE: 'M',
                DESCRIPTION: "{{'EnrollmentSummary_Male' | translate}}"
            },
            {
                VALUE: 'U',
                DESCRIPTION: "{{'EnrollmentSummary_Unknown' | translate}}"
            }
        ];

        vm.policyHoldersCurrentActivePlans = [];

        vm.addReasonCodesList = null;
        vm.relationshipCodesAddDependentList = null;
        vm.stateList = null;

        vm.eMode = enrollmentSummaryModes;

        vm.isImpersonation = DataService.IsImpersonation;

        vm.$onInit = function () {
            vm.enrolleeId = 0;
            vm.insuredEnrolleeId = DataService.EnrolleeId;
            vm.previousState.params.editSaveSuccessful = false;
            vm.previousState.params.addSaveSuccessful = false;
            vm.userIsSubscriber = DataService.userIsSubscriber;
            vm.insurerId = DataService.InsurerId;
            vm.mode = $stateParams.mode;
            vm.hasDependents = $stateParams.hasDependents;
            vm.getRelationshipCodesAddDependent();
            vm.getStateList();
            vm.getPolicyHoldersCurrentActivePlans();
            vm.scrollTop();
            vm.addData.SAME_AS_SUBSCRIBER = true;
            vm.todayMinus30Days = moment().subtract(30, 'days').format("MM/DD/yyyy");
            vm.customErrors = {
                QualifyingEventDateTextBox: {
                    isAfter: `EnrollmentSummary_AddDependent_Validation_QualifyingEventDatePrior30DaysLong {{ \\"voicePhone\\": \\"${DataService.PortalInfo.VoicePhone}\\" , \\"email\\": \\"${DataService.PortalInfo.CustomerServiceEmail}\\" }}`,
                    isBirthDate: 'EnrollmentSummary_AddDependent_Validation_DobMustMatchEventDate'
                },
                DateOfBirthTextBox: {
                    isBirthDate: 'EnrollmentSummary_AddDependent_Validation_DobMustMatchEventDate',
                    isOlderThanDependentAgeCutoff: `EnrollmentSummary_AddDependent_Validation_DependentMustBeYoungerThanAgeCutoff ((dependentAgeCutoff: ${DataService.DependentAgeCutoff}))`         
                }
            };
            vm.customErrorsInline = {
                QualifyingEventDateTextBox: {
                    isAfter: `EnrollmentSummary_AddDependent_Validation_QualifyingEventDatePrior30DaysShort`,
                },
            };
            vm.isFutureEligibility = DataService.IsFutureEligibility;
            vm.addDependentDateError = undefined;
            vm.addDependentCombinationError = undefined;
            vm.addDependentBillingFrequencyError = undefined;
            vm.billingCycleType = $stateParams.billingCycleType;
            vm.billingCycleTypeName = $stateParams.billingCycleTypeName;

            vm.isOpenEnrollmentFlag = false;
            openEnrollmentService.getIsOpenEnrollment()
                .then(function successCallback(response) {
                    if (response) {
                        vm.isOpenEnrollmentFlag = response.isOpenEnrollment;
                        vm.getAddReasonCodesForDependent();
                        if (vm.isOpenEnrollmentFlag) vm.addData.QUALIFYING_EVENT_DATE = new Date().formatMMDDYYYY();
                    }
                });
        };

        vm.setStep = function (step) {
            vm.step = step;
        };

        vm.getBackButtonTranslationParams = function () {
            return {
                type: $stateParams.backToText
            }
        };
        vm.getSaveButtonTranslationParams = function () {
            return {
                accountName: null
            };
        };

        vm.getAddReasonCodesForDependent = function () {
            if (vm.addReasonCodesList !== null)
                return;

            enrollmentSummaryService.getAddReasonCodesForDependent(vm.isOpenEnrollmentFlag)
                .then(function successCallback(response) {
                    vm.addReasonCodesList = response.data;

                    if (vm.isOpenEnrollmentFlag) {
                        vm.addData.QUALIFYING_EVENT = RENEWAL_PERIOD_CHANGE_ADD_REASON_CODE;
                    }
                });
        };

        vm.getRelationshipCodesAddDependent = function () {
            if (vm.relationshipCodesAddDependentList !== null)
                return;

            enrollmentSummaryService.getRelationshipCodesAddDependent()
                .then(function successCallback(response) {
                    vm.relationshipCodesAddDependentList = response.data;
                });
        };

        vm.getStateList = function () {
            if (vm.stateList !== null)
                return;

            enrollmentSummaryService.getStateList()
                .then(function successCallback(response) {
                    vm.stateList = response;
                });
        };

        function isSpouse() {
            return DataService.DependentType === DEPENDENT_TYPE_SPOUSE;
        }

        vm.getChildCountFromDependentsList = function () {
            return DataService.Dependents.filter(function (dependent) {
                return dependent.RELATIONSHIP_CODE === RELATIONSHIP_CODE_CHILD && dependent.ENROLLMENT_STATUS_CODE === ACTIVE_DEPENDENT_CODE;
            }).length || 0;
        };

        vm.getPolicyHoldersCurrentActivePlans = function () {
            var policyHoldersCurrentActivePlanDTO = {
                enrolleeId: DataService.EnrolleeId,
                premiumGroupId: DataService.GroupId,
                productId: DataService.ProductId,
                spouseFlag: isSpouse(),
                childCount: vm.getChildCountFromDependentsList(),
                dependentType: DataService.DependentType
            };
            enrollmentSummaryService.getPolicyHoldersCurrentActivePlans(policyHoldersCurrentActivePlanDTO)
                .then(function successCallback(response) {
                    vm.policyHoldersCurrentActivePlans = response.data;
                });
        };
        vm.isAnyProductSelected = function () {
            return vm.policyHoldersCurrentActivePlans.some(x => x.isSelected);
        };
        vm.goBack = function () {
            $state.go(vm.previousState.name, vm.previousState.params)
        };

        vm.scrollTop = function (tag) {
            $('html, body').animate({ scrollTop: 0 }, 'slow');
        };

        Date.prototype.formatMMDDYYYY = function () {
            return (("0" + (this.getMonth() + 1)).slice(-2)) +
                "/" + ("0" + this.getDate()).slice(-2) +
                "/" + ("0" + this.getFullYear()).slice(-4);
        };

        function isOlderThanDependentAgeCutoff(dateOfBirth) {
            let dobDiff = Date.now() - new Date(dateOfBirth);
            let dobDiffDate = new Date(dobDiff);
            let currentAge = Math.abs(dobDiffDate.getUTCFullYear() - 1970);

            return currentAge > +vm.dependentAgeCutoff;
        }

        vm.onQualifyingEventChange = function () {
            if (vm.addData.QUALIFYING_EVENT == RENEWAL_PERIOD_CHANGE_ADD_REASON_CODE) {
                vm.addDependentBillingFrequencyError = undefined;
                vm.addForm.$setPristine(true);
                vm.addForm.$setUntouched(true);
                vm.addData.QUALIFYING_EVENT_DATE = new Date().formatMMDDYYYY();
            } else {
                vm.addData.QUALIFYING_EVENT_DATE = undefined;
            }
        }

        vm.validateBirthQualifyingType = function () {
            const QUALIFYING_EVENT_BIRTH_CODE = 2;

            const isBirthCode = vm.addData.QUALIFYING_EVENT === QUALIFYING_EVENT_BIRTH_CODE;
            const isDateOfBirthMatchEventDate = vm.addData.QUALIFYING_EVENT_DATE === vm.addData.DOB;
            const isEventDateValid = (isBirthCode && isDateOfBirthMatchEventDate) || !isBirthCode;
            if (!vm.isFutureEligibility && vm.addData.QUALIFYING_EVENT != RENEWAL_PERIOD_CHANGE_ADD_REASON_CODE && DataService.DependentType === "child") {
                vm.addForm.QualifyingEventDateTextBox.$setValidity('isBirthDate', isEventDateValid);
                vm.addForm.DateOfBirthTextBox.$setValidity('isOlderThanDependentAgeCutoff', !isOlderThanDependentAgeCutoff(vm.addData.DOB));
            }
            vm.addForm.DateOfBirthTextBox.$setValidity('isBirthDate', isEventDateValid);
            vm.errors = wbxListErrorsService.getErrorListForBanner(vm.addForm);

        }

        vm.submitAddDependent = function () {
            vm.customErrorMessageList = [];
            vm.addDependentDateError = undefined;
            vm.addDependentCombinationError = undefined;
            vm.addDependentBillingFrequencyError = undefined;

            if (!vm.isFutureEligibility && vm.addData.QUALIFYING_EVENT != RENEWAL_PERIOD_CHANGE_ADD_REASON_CODE) {
                vm.addForm['DocumentList'].$setValidity('required', vm.documents.length > 0);
            }

            vm.validateBirthQualifyingType();

            if (vm.dependentAgeCutoff && DataService.DependentType === "child") {
                vm.addForm.DateOfBirthTextBox.$setValidity('isOlderThanDependentAgeCutoff', !isOlderThanDependentAgeCutoff(vm.addData.DOB));
            }

            if (vm.addForm.$invalid) {
                vm.errors = wbxListErrorsService.getErrorListForBanner(vm.addForm);
                return;
            }

            const payload = {
                lastName: vm.addData.LAST_NAME,
                firstName: vm.addData.FIRST_NAME,
                middleName: vm.addData.MIDDLE_INITIAL,
                nameSuffix: vm.addData.SUFFIX,
                dateOfBirth: vm.addData.DOB,
                gender: vm.addData.GENDER,
                address1: vm.addData.SAME_AS_SUBSCRIBER ? DataService.GenInfo.ADDRESS1 : vm.addData.ADDRESS1,
                address2: vm.addData.SAME_AS_SUBSCRIBER ? DataService.GenInfo.ADDRESS2 : vm.addData.ADDRESS2,
                city: vm.addData.SAME_AS_SUBSCRIBER ? DataService.GenInfo.CITY : vm.addData.CITY,
                state: vm.addData.SAME_AS_SUBSCRIBER ? DataService.GenInfo.STATE : vm.addData.STATE,
                zip: vm.addData.SAME_AS_SUBSCRIBER ? DataService.GenInfo.ZIP : vm.addData.ZIP,
                phone: vm.addData.PHONE_NUMBER,
                addReasonCode: !vm.isFutureEligibility ? vm.addData.QUALIFYING_EVENT : null,
                addReasonEventDate: !vm.isFutureEligibility ? vm.addData.QUALIFYING_EVENT_DATE : null,
                products: vm.policyHoldersCurrentActivePlans.filter(x => x.isSelected).map(x => ({ productId: x.productId, premiumGroupId: x.premiumGroupId, productDescription: x.productDescription })),
                relationshipCode: DataService.DependentType === "child" ? RELATIONSHIP_CODE_CHILD : vm.addData.RELATIONSHIP,
                documentIds: vm.isFutureEligibility || vm.addData.QUALIFYING_EVENT == RENEWAL_PERIOD_CHANGE_ADD_REASON_CODE ? null : vm.documents.map(x => x.documentId),
                isFutureEligibility: vm.isFutureEligibility,
                subscriberEffectiveDate: DataService.GenInfo.EFFECTIVE_DATE,
                isOpenEnrollment: vm.isOpenEnrollmentFlag,
                billingCycleType: vm.billingCycleType
            };

            validatePlans(payload);
        };

        function openAddDependentConfirmationModal(payload) {
            var modalDefaults = {
                backdrop: 'static',
                keyboard: true,
                modalFade: true,
                component: 'addDependentConfirmationModalComponent',
                size: 'md',
                windowClass: "",
                resolve: {
                    payload: function () { return payload; }
                }
            };
            wbxModalService.showModal(modalDefaults, {}).then(function (response) {
                if (response.result !== "submit") return;
                payload.products = response.data;
                enrollmentSummaryService.addDependent(payload)
                    .then(function (response) {
                        vm.previousState.params.addSaveSuccessful = true;
                        DataService.Dependents = response.data.dependents;
                        vm.goBack();
                    }, function (data) {
                        if (typeof (data.errors) !== 'object') return;
                        const errors = Object.keys(data.errors).map(errorKey => ({
                            messageTranslationKey: errorKey,
                            params: {
                                plansCantAddDependent: typeof (data.errors[errorKey]) === 'object' ? data.errors[errorKey].join(", ") : undefined,
                                voicePhone: DataService.PortalInfo.VoicePhone,
                                email: DataService.PortalInfo.CustomerServiceEmail,
                            }
                        }));
                        vm.customErrorMessageList.push(...errors);
                    });
            });
        }

        function validatePlans(payload) {
            var inputValidate = {
                eventDate: payload.addReasonEventDate,
                isFutureEligibility: payload.isFutureEligibility,
                subscriberEffectiveDate: payload.subscriberEffectiveDate,
                plans: payload.products,
                addReasonCode: payload.addReasonCode,
                premiumGroupId: DataService.GroupId,
                enrolleeType: payload.relationshipCode,
                billingCycle: DataService.billingCycleType
            };

            enrollmentSummaryService.validateAddDependent(inputValidate)
                .then(function (result) {
                    payload.effectiveDate = result.data.EffectiveDate;
                    payload.plansToAdd = result.data.PlansToAdd;
                    payload.plansToAddString = concatenate(payload.plansToAdd);

                    if (result.data.PlansCantAddDate.length > 0 && result.data.PlansToAdd.length == 0) {
                        vm.addDependentDateError = {
                            Message: 'AddDependentModal_TerminationDateError',
                            Params: {
                                plansCantAddDate: concatenate(result.data.PlansCantAddDate)
                            }
                        };
                    }

                    if (result.data.PlansCantAddDependent.length > 0 && result.data.PlansToAdd.length == 0) {
                        vm.addDependentCombinationError = {
                            Message: 'AddDependentModal_DependentCombinationError',
                            Params: {
                                plansCantAddDependent: concatenate(result.data.PlansCantAddDependent),
                                phone: DataService.PortalInfo.VoicePhone,
                                email: DataService.PortalInfo.CustomerServiceEmail
                            }
                        };
                    }

                    if (result.data.PlansToAdd.length > 0) {
                        preValidateAddDependent(payload)
                    }
                });
        }

        function preValidateAddDependent(payload) {
            enrollmentSummaryService.preValidateAddDependent(payload)
                .then(function () {
                    openAddDependentConfirmationModal(payload);
                }, function (data) {
                    if (typeof (data.errors) !== 'object') return;
                    const errors = Object.keys(data.errors).map(errorKey => ({
                        messageTranslationKey: errorKey,
                        params: {
                            voicePhone: DataService.PortalInfo.VoicePhone,
                            email: DataService.PortalInfo.CustomerServiceEmail,
                            dependentAgeCutoff: vm.dependentAgeCutoff
                        },
                        extraInfo: typeof (data.errors[errorKey]) === 'string' ? data.errors[errorKey] : undefined
                    }))
                    vm.customErrorMessageList.push(...errors);
                });
        }

        function concatenate(productList) {
            return productList.map(function (product) { return product.productDescription; }).join(", ");
        }
    }
})();;
(function () {
    'use strict';
    angular
        .module('MWPApp')
        .component('editEnrollmentSummary', {
            templateUrl: 'editEnrollmentSummaryTemplate',
            controller: editEnrollmentSummaryController,
            controllerAs: 'vm',
            bindings: {
                previousState: '<'
            }
        });

    editEnrollmentSummaryController.$inject = ['DataService', 'EnrollmentSummaryService', '$state', '$stateParams', 'enrollmentSummaryModes', 'wbxListErrorsService'];
    function editEnrollmentSummaryController(DataService, EnrollmentSummaryService, $state, $stateParams, enrollmentSummaryModes, wbxListErrorsService) {
        var vm = this;
        vm.editData = {};
        vm.editDependentIndex = null;
        vm.GenderList = [
            {
                VALUE: 'F',
                DESCRIPTION: "Female"
            },
            {
                VALUE: 'M',
                DESCRIPTION: "Male"
            },
            {
                VALUE: 'U',
                DESCRIPTION: "Unknown"
            }
        ];

        vm.YesNoList = [
            {
                VALUE: false,
                DESCRIPTION: "No"
            },
            {
                VALUE: true,
                DESCRIPTION: "Yes"
            }
        ];

        vm.maritalStatusesList = null;
        vm.stateList = null;

        vm.eMode = enrollmentSummaryModes;

        vm.isImpersonation = DataService.IsImpersonation;
        
        vm.$onInit = function () {
            vm.previousState.params.editSaveSuccessful = false;
            vm.userIsSubscriber = DataService.userIsSubscriber;
            vm.mode = $stateParams.mode;
            vm.hasDependents = $stateParams.hasDependents
            vm.getMaritalStatuses();
            vm.getStateList();
            vm.scrollTop();
            vm.editData = $stateParams.data;
        };

        vm.getBackButtonTranslationParams = function () {
            return {
                type: $stateParams.backToText
            }
        };
        vm.getSaveButtonTranslationParams = function () {
            return {
                accountName: vm.editData.FIRST_NAME + " " + vm.editData.LAST_NAME
            };
        };
        vm.getMaritalStatuses = function () {
            if (vm.maritalStatusesList !== null)
                return;

            var promise = EnrollmentSummaryService.getMaritalStatuses();
            promise.then(function successCallback(response) {
                vm.maritalStatusesList = response;
            },
                function errorCallback(response) {
                    console.error(response.Message);
                    console.error(response);
                    if ($scope.ExceptionDialogControl !== null) {
                        $scope.ExceptionDialogControl
                            .showDialog("Error retrieving marital statuses.");
                    }
                });
        };

        vm.getStateList = function () {
            if (vm.stateList !== null)
                return;

            var promise = EnrollmentSummaryService.getStateList();
            promise.then(function successCallback(response) {
                vm.stateList = response;
            },
                function errorCallback(response) {
                    console.error(response.Message);
                    console.error(response);
                    if ($scope.ExceptionDialogControl !== null) {
                        $scope.ExceptionDialogControl
                            .showDialog("Error retrieving states.");
                    }
                });
        };

        vm.saveEdit = function () {
            if (vm.editForm.$invalid) {
                vm.errors = wbxListErrorsService.getErrorListForBanner(vm.editForm)
                return;
            }

            var promise = EnrollmentSummaryService.saveEdit(vm.editData);
            promise.then(function successCallback() {
                vm.previousState.params.editSaveSuccessful = true;

                if (vm.mode === enrollmentSummaryModes.EDIT_SUBSCRIBER || (vm.mode === enrollmentSummaryModes.EDIT_DEPENDENT && !$stateParams.isUserSubscriber)) {
                    vm.updateMemberData(DataService.GenInfo);
                } else {
                    const dependentIndex = _.findIndex(DataService.Dependents, function (item) {
                        return item.ENROLLEE_ID === vm.editData.ENROLLEE_ID;
                    });
                    vm.updateMemberData(DataService.Dependents[dependentIndex]);
                    if (vm.previousState.params.data !== undefined)
                        vm.updateMemberData(vm.previousState.params.data);
                }

                if (vm.editData.APPLY_TO_ALL) {
                    // udpate each dependent contact info
                    DataService.Dependents.forEach(function (dependent) {
                        vm.setContactInfo(dependent);
                    });
                    vm.setContactInfo(DataService.GenInfo);
                    if (vm.previousState.params.data !== undefined)
                    vm.setContactInfo(vm.previousState.params.data);
                }

                vm.goBack();

            }, function errorCallback(response) {
                vm.editSaveUnsuccessful = true;
            });

        }

        vm.setContactInfo = function (member) {
            member.ADDRESS1 = vm.editData.ADDRESS1;
            member.ADDRESS2 = vm.editData.ADDRESS2;
            member.CITY = vm.editData.CITY;
            member.STATE = vm.editData.STATE;
            member.ZIP = vm.editData.ZIP;
            member.ZIP_4 = vm.editData.ZIP_4;
            member.PHONE_NUMBER = vm.editData.PHONE_NUMBER;
            member.PHONE_EXTENSION = vm.editData.PHONE_EXTENSION;
        }

        vm.updateMemberData = function (member) {
            member.FIRST_NAME = vm.editData.FIRST_NAME;
            member.MIDDLE_NAME = vm.editData.MIDDLE_NAME;
            member.LAST_NAME = vm.editData.LAST_NAME;
            member.DOB = vm.editData.DOB;
            member.GENDER = vm.editData.GENDER;
            var SSN = vm.editData.SS_NUMBER.replace(/-/g, '');
            member.SS_NUMBER = SSN;

            if (SSN >= 9)
                member.LAST_4_SSN = SSN.substring(5, 9);
            else
                member.LAST_4_SSN = "";
            member.MARITAL_STATUS = vm.editData.MARITAL_STATUS;
            member.HANDICAP_FLAG = vm.editData.HANDICAP_FLAG;
            member.ADDRESS1 = vm.editData.ADDRESS1;
            member.ADDRESS2 = vm.editData.ADDRESS2;
            member.CITY = vm.editData.CITY;
            member.STATE = vm.editData.STATE;
            member.ZIP = vm.editData.ZIP;
            member.ZIP_4 = vm.editData.ZIP_4;
            member.PHONE_NUMBER = vm.editData.PHONE_NUMBER;
            member.PHONE_EXTENSION = vm.editData.PHONE_EXTENSION;
        }


        vm.goBack = function () {
            $state.go(vm.previousState.name, vm.previousState.params)

        };

        vm.scrollTop = function (tag) {

            $('html, body').animate({ scrollTop: 0 }, 'slow');
        }


        Date.prototype.formatMMDDYYYY = function () {
            return (("0" + (this.getMonth() + 1)).slice(-2)) +
                "/" + ("0" + this.getDate()).slice(-2) +
                "/" + ("0" + this.getFullYear()).slice(-4);
        }
    }

})();
;
(function () {
    //@LA TODO: Split dependent view and subcriber view in to two different components and new component for common block (general info display)
    'use strict';
    angular
        .module('MWPApp')
        .component('enrollmentSummary', {
            templateUrl: 'enrollmentSummaryTemplate',
            controller: enrollmentSummaryController,
            controllerAs: 'vm',
            bindings: {
            }
        });

    enrollmentSummaryController.$inject = ['$http', 'DataService', 'EnrollmentSummaryService', '$window', '$q', '$state', 'enrollmentSummaryModes', '$stateParams', '$timeout', '$sce', '$translate', 'wbxListErrorsService', 'WbxModalService', 'OpenEnrollmentService', '$scope', 'PrintCardService'];
    function enrollmentSummaryController($http, DataService, EnrollmentSummaryService, $window, $q, $state, enrollmentSummaryModes, $stateParams, $timeout, $sce, $translate, wbxListErrorsService, wbxModalService, openEnrollmentService, $scope, PrintCardService) {
        const ENROLLMENT_STATUS_CODE_ACTIVE = 1;
        const DEPENDENT_TYPE_SPOUSE = "spouse";
        const DEPENDENT_TYPE_CHILD = "child";
        const BACK_TO_TEXT_MEMBER = "member";
        const RELATIONSHIP_CODE_CHILD = "19";
        const RELATIONSHIP_CODE_SPOUSE = "01";
        const RELATIONSHIP_CODE_LIFE_PARTNER = "53";
        const ACTIVE_DEPENDENT_CODE = 1;
        const FUTURE_DEPENDENT_CODE = 2;
        const QUALIFYING_EVENT_TYPE = "Drop dependent";
        const QUALIFYING_EVENT_DATE_PAST = "EnrollmentSummary_DropDependentModal_QualifyingEventDatePast";
        const QUALIFYING_EVENT_DATE_ADD_PAST = "EnrollmentSummary_AddDependent_Validation_QualifyingEventDatePrior30DaysLong";
        const QUALIFYING_EVENT_DATE_PAST_INLINE = "EnrollmentSummary_DropDependentModal_QualifyingEventDatePast_Inline";
        const QUALIFYING_EVENT_DATE_FUTURE = "EnrollmentSummary_DropDependentModal_QualifyingEventDateFuture";
        const DROP_DEPENDENT_MODAL_STEP_1 = 1;
        const DROP_DEPENDENT_MODAL_STEP_2 = 2;
        const QUALIFYING_EVENT_TYPE_ADD_DEPENDENT = "Add dependent";
        const BIRTH_REASON_CODE = 2
        const QUALIFYING_EVENT_TYPE_BIRTH_DATE = "EnrollmentSummary_AddDependent_Validation_DobMustMatchEventDate";
        const RENEWAL_PERIOD_CHANGE_ADD_REASON_CODE = 8;
        const RENEWAL_PERIOD_CHANGE_TERMINATION_REASON_CODE = 10;

        var vm = this;
        var userIsSubscriber = undefined;

        vm.focusMainRequestCardIcon = false;
        vm.eMode = enrollmentSummaryModes;
        vm.qualifyingEventType = QUALIFYING_EVENT_TYPE;
        vm.qualifyingEventDatePastInline = QUALIFYING_EVENT_DATE_PAST_INLINE;
        vm.qualifyingEventDateFuture = QUALIFYING_EVENT_DATE_FUTURE;
        vm.dropDependentModalStep1 = DROP_DEPENDENT_MODAL_STEP_1;
        vm.dropDependentModalStep2 = DROP_DEPENDENT_MODAL_STEP_2;
        vm.enrolleeDependent = {};
        vm.getPlansTranslationParams = getPlansTranslationParams;
        vm.getCantDropPlansCombinationTranslationParams = getCantDropPlansCombinationTranslationParams;
        vm.showDropDependentButton = showDropDependentButton;
        vm.isNotMonthlyBillingCycleType = isNotMonthlyBillingCycleType;
        vm.getDropDependentTooltipText = getDropDependentTooltipText;
        vm.qualifyingEventTypeAdd = QUALIFYING_EVENT_TYPE_ADD_DEPENDENT;
        vm.qualifyingEventDateBirth = QUALIFYING_EVENT_TYPE_BIRTH_DATE;
        vm.renewalPeriodChangeAddReasonCode = RENEWAL_PERIOD_CHANGE_ADD_REASON_CODE;
        vm.renewalPeriodChangeTerminationReasonCode = RENEWAL_PERIOD_CHANGE_TERMINATION_REASON_CODE;
        vm.changeQualifyingEventDropDependent = changeQualifyingEventDropDependent;
        vm.isDependentWithPhiFullAccess = isDependentWithPhiFullAccess;
        vm.getDependentOptionTooltip = getDependentOptionTooltip;
        vm.canUpgradeBenefitTier = canUpgradeBenefitTier;
        vm.isDependentDisplayableWithoutPhiAccess = isDependentDisplayableWithoutPhiAccess;
        vm.benefitSummaryEnrolleeId = DataService.EnrolleeId;
        vm.selectedEnrolleeId = DataService.EnrolleeId;
        vm.benefitSummaryEnrolleeId = 0;
        vm.isVision = DataService.IsVision;
        vm.productLOB = DataService.productLineOfBusiness;
        vm.showBenefitSummaryReportLink = DataService.ShowBenefitSummaryLink;
        vm.isDentalMvcBenefitSummaryReport = DataService.IsDentalMvcBenefitSummaryReport;
        const DENTAL = 2;

        if (window.document.documentMode == undefined) {
            vm.editSaveSuccessful = $stateParams.editSaveSuccessful;
            vm.addSaveSuccessful = $stateParams.addSaveSuccessful;

        }
        else {
            $timeout(function () {
                vm.editSaveSuccessful = $stateParams.editSaveSuccessful;
            }, 1000)
        }

        vm.isImpersonation = DataService.IsImpersonation;

        vm.$onInit = function () {
            vm.displayCustomInfoBanner = false;
            vm.billingCycleType = undefined;
            vm.billingCycleTypeName = undefined;
            vm.escalationTier = undefined;
            setPageTitle('Member Information');
            vm.scrollTop();
            vm.eMode = enrollmentSummaryModes;
            vm.permissions = DataService.permissions;

            vm.insurerId = DataService.InsurerId;
            vm.canDropChildFlag = undefined;
            setupGeneralInfo();
            userIsSubscriber = DataService.userIsSubscriber;
            vm.mode = $stateParams.mode || (
                userIsSubscriber
                    ? vm.eMode.SUBSCRIBER
                    : vm.eMode.DEPENDENT);
            vm.productId = DataService.ProductId;
            vm.groupId = DataService.GroupId;
            vm.enrolleeId = $stateParams.data ? $stateParams.data.ENROLLEE_ID : DataService.EnrolleeId;
            vm.useCustomBenefitSummaryReport = DataService.get("IsCustomBenefitSummaryReport");
            if (vm.mode === 2) {
                setPageTitle('Dependent Information');
            }
            if (DataService.ViewEnrolleeId)
                setEnrolleeActive(DataService.ViewEnrolleeId);

            $('#RequestIDCardDialogDesktop').on('hidden.bs.modal', function () {
                vm.closeRequestIdDialog();
            });
            $('#RequestIDCardDialogMobile').on('hidden.bs.modal', function () {
                vm.closeRequestIdDialog();
            });
            vm.voicePhone = DataService.get("PortalInfo")['VoicePhone'];
            vm.customerServiceEmail = DataService.get("PortalInfo")['CustomerServiceEmail'];
            initAddDependentToPlanForm();
            initDropDependentForm();
            getEscalationTier();

            if (Boolean(DataService.get("HasApiSetup"))) {
                initIndividualEnrollmentFeatures();
            }
            vm.isAccumulatorInformationConfigurated = DataService.IsAccumulatorInformationConfigurated;
        };

        function getEscalationTier() {
            EnrollmentSummaryService.getEscalationTier({
                productId: DataService.ProductId,
                premiumGroupId: DataService.GroupId,
                enrolleeId: DataService.EnrolleeId,
                terminationDate: DataService.GenInfo.TERMINATION_DATE,
            }).then(response => { vm.escalationTier = response.data; });
        }

        vm.getTitleTranslationParam = function () {
            return {
                dependentAgeCutoff: vm.enrolleeDependent.dependentAgeCutoff,
                billingFrequency: vm.billingCycleTypeName,
                customerServicePhone: DataService.PortalInfo.VoicePhone,
                customerServiceEmail: DataService.PortalInfo.CustomerServiceEmail
            };
        };

        function initAddDependentToPlanForm() {
            vm.todayMinus30Days = moment().subtract(30, 'days').format("MM/DD/yyyy");
            vm.addDependentToPlanFormCustomErrors = {
                EventDateTextBox: {
                    isAfter: `${QUALIFYING_EVENT_DATE_ADD_PAST} {{ \\"voicePhone\\": \\"${DataService.get("PortalInfo")['VoicePhone']}\\" , \\"email\\": \\"${DataService.get("PortalInfo")['CustomerServiceEmail']}\\" }}`,
                }
            };
            vm.addDependentToPlanFormCustomErrorsInline = {
                EventDateTextBox: {
                    isAfter: `${QUALIFYING_EVENT_DATE_PAST_INLINE}`,
                }
            };
        }

        function initDropDependentForm() {
            vm.todayMinus30Days = moment().subtract(30, 'days').format("MM/DD/yyyy");
            vm.dropDependentFormCustomErrors = {
                EventDateTextBox: {
                    isAfter: `${QUALIFYING_EVENT_DATE_PAST} {{ \\"voicePhone\\": \\"${DataService.get("PortalInfo")['VoicePhone']}\\" , \\"email\\": \\"${DataService.get("PortalInfo")['CustomerServiceEmail']}\\" }}`,
                }
            };
            vm.dropDependentFormCustomErrorsInline = {
                EventDateTextBox: {
                    isAfter: `${QUALIFYING_EVENT_DATE_PAST_INLINE}`,
                }
            };
        }

        function setupGeneralInfo() {
            const generalInfo = $stateParams.data === undefined
                ? DataService.GenInfo
                : $stateParams.data;

            vm.genInfo = generalInfo;
            setupCurrentEnrollee(generalInfo);

            vm.dependents = DataService.Dependents.length > 0
                ? DataService.Dependents
                : null;
        }
        function initIndividualEnrollmentFeatures() {

            validateOpenEnrollment(function () {
                if (vm.isOpenEnrollmentFlag) {
                    EnrollmentSummaryService.getCurrentEnrolleeContract()
                        .then(function (currentEnrolleeContract) {
                            vm.billingCycleType = currentEnrolleeContract.BillingCycleType;
                            vm.billingCycleTypeName = currentEnrolleeContract.BillingCycleTypeName;
                            DataService.billingCycleType = vm.billingCycleType;
                            DataService.billingCycleTypeName = vm.billingCycleTypeName;
                            vm.isIndividualEnrollment(function () {
                                vm.planAllowsDependents();
                            });
                        })
                } else {
                    EnrollmentSummaryService.getEnrolleeBillingCycleType()
                        .then(function (enrolleeBillingCycleType) {
                            vm.billingCycleType = enrolleeBillingCycleType.billingCycleType;
                            DataService.billingCycleType = vm.billingCycleType;
                            vm.billingCycleTypeName = enrolleeBillingCycleType.billingCycleTypeName;
                            vm.isIndividualEnrollment(function () {
                                vm.planAllowsDependents();
                            });
                        });
                }
            })

            vm.canDropDependents();

        }

        function setEnrolleeActive(enrolleeId) {
            if (!enrolleeId)
                return;
            if (vm.genInfo.ENROLLEE_ID === enrolleeId)
                vm.currentEnrollee = vm.genInfo;
            else {
                vm.dependents.forEach(function (dependent) {
                    if (dependent.ENROLLEE_ID === enrolleeId) {
                        vm.mode = vm.eMode.VIEWING_DEPENDENT;
                        setPageTitle('View Dependent');
                        vm.currentEnrollee = dependent;
                    }
                });

            }
        }

        vm.editUser = function () {
            setPageTitle('Edit Policy Holder');
            getSSN(vm.currentEnrollee.ENROLLEE_ID).then(function (response) {
                let editData = getEditData(vm.currentEnrollee);
                editData.SS_NUMBER = response;
                let mode = vm.mode === enrollmentSummaryModes.SUBSCRIBER
                    ? enrollmentSummaryModes.EDIT_SUBSCRIBER
                    : enrollmentSummaryModes.EDIT_DEPENDENT;
                const backToText = vm.mode === enrollmentSummaryModes.DEPENDENT && userIsSubscriber ? 'dependent' : 'member';
                navigateToEditPage(editData, mode, backToText);
            });
        };

        vm.addSpouse = function () {
            DataService.DependentType = DEPENDENT_TYPE_SPOUSE;
            setPageTitle('Add Dependent');
            navigateToAddPage(null, enrollmentSummaryModes.EDIT_DEPENDENT, BACK_TO_TEXT_MEMBER);
        };

        vm.addChild = function () {
            DataService.DependentType = DEPENDENT_TYPE_CHILD;
            setPageTitle('Add Dependent');
            navigateToAddPage(null, enrollmentSummaryModes.EDIT_DEPENDENT, BACK_TO_TEXT_MEMBER);
        };

        vm.editDependent = function (index) {
            setPageTitle('Edit Dependent');
            if (vm.dependents === null || index >= vm.dependents.length)
                return;

            getSSN(vm.dependents[index].ENROLLEE_ID).then(function (response) {
                let editData = getEditData(vm.dependents[index]);
                editData.SS_NUMBER = response;
                navigateToEditPage(editData, enrollmentSummaryModes.EDIT_DEPENDENT, BACK_TO_TEXT_MEMBER);
            });
        };

        function navigateToAddPage(editMode, backToText) {
            $state.go('addEnrollmentSummary', { data: null, mode: editMode, hasDependents: vm.dependents !== null, isUserSubscriber: userIsSubscriber, backToText: backToText, billingCycleType: vm.billingCycleType, billingCycleTypeName: vm.billingCycleTypeName });
        }

        function navigateToEditPage(editData, editMode, backToText) {
            const type = editMode === enrollmentSummaryModes.EDIT_SUBSCRIBER ? 'subscriber' : 'dependent';
            $state.go('editEnrollmentSummary', { data: editData, mode: editMode, hasDependents: vm.dependents !== null, isUserSubscriber: userIsSubscriber, type: type, backToText: backToText });
        }

        function setPageTitle(title) {
            document.title = title;
        }

        function getSSN(enrolleeId) {
            let promise = undefined;
            promise = EnrollmentSummaryService.getMemberSSN(enrolleeId).then(
                function (response) {
                    return response.SSN !== null
                        ? response.SSN.trim()
                        : "";
                },
                function errorCallback(response) {
                    console.error(response);
                });
            return promise;
        }

        function getEditData(source) {
            let editData = {};
            editData.ENROLLEE_ID = source.ENROLLEE_ID;
            editData.FIRST_NAME = source.FIRST_NAME;
            editData.MIDDLE_NAME = source.MIDDLE_NAME;
            editData.LAST_NAME = source.LAST_NAME;
            editData.DOB = (new Date(source.DOB)).formatMMDDYYYY();
            editData.GENDER = source.GENDER;
            editData.SSN = source.SSN;
            editData.MARITAL_STATUS = source.MARITAL_STATUS;
            editData.HANDICAP_FLAG = source.HANDICAP_FLAG;
            editData.ADDRESS1 = source.ADDRESS1;
            editData.ADDRESS2 = source.ADDRESS2;
            editData.CITY = source.CITY;
            editData.STATE = source.STATE;
            editData.ZIP = source.ZIP;
            editData.ZIP_4 = source.ZIP_4;
            editData.PHONE_NUMBER = source.PHONE_NUMBER;
            editData.PHONE_EXTENSION = source.PHONE_EXTENSION;
            editData.APPLY_TO_ALL = false;

            return editData;
        }

        function displayNoAccessCustomBenefitSummaryReport() {
            var modalDefaults = {
                backdrop: 'static',
                keyboard: true,
                modalFade: true,
                component: 'noAccessCustomBenefitSummaryReport',
                size: 'md',
                windowClass: ""
            };
            wbxModalService.showModal(modalDefaults, {});
        }

        vm.printIdCard = function (enrolleeId) {
            if (enrolleeId === undefined)
                enrolleeId = vm.currentEnrollee.ENROLLEE_ID;

            vm.javaScriptBlockMessage = false;
            vm.unumPrintIdCardRequest = false;
            vm.isRequestIdLoading = true;

            var sessionProperties = [];
            var sessionProperty =
            {
                SESSION_NAME: 'PRINT_ENROLLEE_ID',
                SESSION_VALUE: enrolleeId
            }
            sessionProperties.push(sessionProperty);

            PrintCardService.UseUnum().then(response => {
                if (!response.Status) {

                    var url = '/Areas/MWP/Reports/MemberIDCard.aspx';
                    vm.isRequestIdLoading = false;
                    vm.openTab(url, sessionProperties);
                } else {

                    PrintCardService.IdCardPdf()
                        .then(response => {
                            if (response?.type?.indexOf("application/pdf") > -1) {
                                var file = new Blob([response], { type: response.type });
                                var fileUrl = URL.createObjectURL(file)
                                var newWindow = window.open('', "_blank");
                                if (!newWindow || newWindow.closed || typeof newWindow.closed == 'undefined') {

                                    vm.javaScriptBlockMessage = true;
                                    vm.scrollTop();
                                }

                                var promise = vm.setSessionProperties(sessionProperties);
                                promise.then(function () {
                                    newWindow.location = fileUrl;
                                    vm.isRequestIdLoading = false;
                                }, function (data) {
                                });
                            } else {
                                vm.unumPrintIdCardRequest = true;
                                vm.scrollTop();
                                vm.isRequestIdLoading = false;
                            }
                        });
                }
            });

        };


        vm.openTab = function (url, sessionProperties) {
            var randomno = Math.floor((Math.random() * 100) + 1);
            var newWindow = $window.open('', 'PopUpWindow' + randomno, 'resizable,scrollbars,width=1000,height=900');
            if (!newWindow || newWindow.closed || typeof newWindow.closed == 'undefined') {

                vm.javaScriptBlockMessage = true;
                vm.scrollTop();
            }
            var promise = vm.setSessionProperties(sessionProperties);
            promise.then(function () {
                newWindow.location = url;
            }, function (data) {
            });
        };

        vm.setSessionProperties = function (sessionProperties) {
            var deferred = $q.defer();

            $http({
                url: "/PortalWebSession/SetWebSessionProperties",
                method: "PUT",
                data: {
                    SESSION_PROPERTIES: sessionProperties
                }
            }).then(function successCallback(response) {
                if (!response.data.Status) {
                    deferred.reject(false);
                    console.error(response.data.Message);
                    console.error(response);
                    vm.ExceptionDialogControl.showDialog("Error with setting session properties.");
                }
                else {
                    deferred.resolve(true);
                }
            }, function errorCallback(response) {
                deferred.reject(false);
                console.error(response.data.Message);
                console.error(response);
                vm.ExceptionDialogControl.showDialog("Error with setting session properties.");
            });

            return deferred.promise;
        };

        vm.getMemberInfo = function (enrolleeId) {
            var promise = EnrollmentSummaryService.getMemberInfo(enrolleeId);
            promise.then(function successCallback(response) {
                vm.memberInfo = response.data;
            },
                function errorCallback(response) {
                    console.error(response.Message);
                    console.error(response);
                    if ($scope.ExceptionDialogControl !== null) {
                        $scope.ExceptionDialogControl
                            .showDialog("Error retrieving member information.");
                    }
                });

        };

        vm.showRequestIdDialog = function () {
            $('#RequestIDCardDialogDesktop').modal({
                backdrop: 'static'
            });
            $('#RequestIDCardDialogDesktop').modal('show');

            $('#RequestIDCardDialogMobile').modal({
                backdrop: 'static'
            });
            $('#RequestIDCardDialogMobile').modal('show');
        };

        vm.showDropDependentModalDialog = function () {
            $('#DropDependentModalDialog').modal({
                backdrop: 'static'
            });
            $('#DropDependentModalDialog').modal('show');
        };

        vm.requestIdCard = function () {
            vm.getMemberInfo(vm.currentEnrollee.ENROLLEE_ID);
            vm.showRequestIdDialog();
            vm.focusMainRequestCardIcon = true;
        };

        vm.submitRequestId = function () {

            var sessionProperties = [];
            var sessionProperty =
            {
                SESSION_NAME: 'PRINT_ENROLLEE_ID',
                SESSION_VALUE: vm.memberInfo.ENROLLEE_ID
            };
            sessionProperties.push(sessionProperty);
            vm.setSessionProperties(sessionProperties);

            var promise = EnrollmentSummaryService.requestIdCard();
            promise.then(function successCallback(response) {
                vm.closeRequestIdDialog();
                vm.requestIdSuccess = true;
            },
                function errorCallback(response) {
                    vm.closeRequestIdDialog();
                    vm.requestIdFailure = true;
                });

        };


        vm.closeRequestIdDialog = function () {
            if (vm.focusMainRequestCardIcon) {
                setTimeout(function () { angular.element('#RequestIdCardWithText').focus(); }, 1000);
            }
            $('#RequestIDCardDialogDesktop').modal('hide');
            $('#RequestIDCardDialogMobile').modal('hide');
            vm.focusMainRequestCardIcon = false;
        };

        vm.closeDropDependentModalDialog = function () {
            vm.dropDependentModalCustomError = undefined;
            vm.dropDependentModalCustomWarning = undefined;
            vm.dropDependentModalCustomWarningCombination = undefined;
            vm.dropDependentFormValidations = {};
            if (vm.dropDependentForm) {
                vm.dropDependentForm.$setPristine(true);
                vm.dropDependentForm.$setUntouched(true);
            }
            $('#DropDependentModalDialog').modal('hide');
        };

        vm.viewDefaultBenefitSummary = function (enrolleeId) {
            if (enrolleeId === undefined)
                enrolleeId = vm.currentEnrollee.ENROLLEE_ID;

            var sessionProperties = [];
            var sessionProperty =
            {
                SESSION_NAME: 'PRINT_ENROLLEE_ID',
                SESSION_VALUE: enrolleeId
            };
            sessionProperties.push(sessionProperty);
            var url = '/Areas/MWP/Reports/BenefitSummary.aspx';
            vm.openTab(url, sessionProperties);
        };

        vm.viewCustomBenefitSummary = function () {
            EnrollmentSummaryService.getCustomBenefitSummaryReport()
                .then(response => {
                    if (response.type !== "application/json") {
                        var file = new Blob([response], { type: response.type });
                        var fileUrl = URL.createObjectURL(file)
                        window.open(fileUrl, "_blank");
                    } else {
                        displayNoAccessCustomBenefitSummaryReport()
                    }
                });
        };

        vm.viewHistory = function (enrolleeId) {
            if (enrolleeId === undefined)
                enrolleeId = vm.currentEnrollee.ENROLLEE_ID;

            var sessionProperties = [];
            var sessionProperty =
            {
                SESSION_NAME: 'PRINT_ENROLLEE_ID',
                SESSION_VALUE: enrolleeId
            };
            sessionProperties.push(sessionProperty);

            var url = '/Areas/MWP/Reports/EligibilityHistory.aspx';
            vm.openTab(url, sessionProperties);
        };

        vm.viewDependentDetails = function (index) {
            const generalDependentInfo = _.defaults(vm.dependents[index], vm.genInfo)
            $state.go("enrollmentDependentSummary", { data: generalDependentInfo })
        };


        vm.printDependentCard = function (index) {
            if (vm.dependents !== null && index >= 0 && index < vm.dependents.length)
                vm.printIdCard(vm.dependents[index].ENROLLEE_ID);
        };

        vm.requestDependentCard = function (index) {
            if (vm.dependents !== null && index >= 0 && index < vm.dependents.length) {
                vm.getMemberInfo(vm.dependents[index].ENROLLEE_ID);
                vm.showRequestIdDialog();
            }
        };

        vm.viewBenefitSummaryRdl = function (enrolleeId) {
            if (enrolleeId === undefined)
                enrolleeId = vm.currentEnrollee.ENROLLEE_ID;

            var sessionProperties = [];
            var sessionProperty =
            {
                SESSION_NAME: 'PRINT_ENROLLEE_ID',
                SESSION_VALUE: enrolleeId
            };
            sessionProperties.push(sessionProperty);
            var url = '/Areas/MWP/Reports/BenefitSummary.aspx';
            vm.openTab(url, sessionProperties);
        };

        vm.viewDependentBenefitSummary = function (index) {
            let enrolleeId = 0;

            if (vm.dependents !== null && index >= 0 && index < vm.dependents.length) {
                enrolleeId = vm.dependents[index].ENROLLEE_ID;
            }
            else {
                enrolleeId = DataService.EnrolleeId;
            }

            if (vm.useCustomBenefitSummaryReport) {
                vm.viewCustomBenefitSummary();
            } else {

                vm.showPortalBenefitSummaryReport(enrolleeId);
            }
            
        };

        vm.showPortalBenefitSummaryReport = function (enrolleeId) {
            if (vm.productLOB != DENTAL || !vm.isDentalMvcBenefitSummaryReport) {
                vm.viewBenefitSummaryRdl(enrolleeId);
            }
            else {
                vm.benefitSummaryEnrolleeId = enrolleeId
                vm.loadBenefitSummaryReportData();
                $('#BenefitSummaryReportModal').modal('show');
            }
            
        }

        vm.viewDependentHistory = function (index) {
            if (vm.dependents !== null && index >= 0 && index < vm.dependents.length)
                vm.viewHistory(vm.dependents[index].ENROLLEE_ID);
        };

        vm.openDropDependentModal = function (index) {
            if (vm.dependents !== null && index >= 0 && index < vm.dependents.length) {
                vm.dropDependentModalDocuments = [];
                vm.dropDependentModel = {
                    EnrolleeId: vm.dependents[index].ENROLLEE_ID,
                    EnrolleeName: vm.dependents[index].FIRST_NAME + " " + vm.dependents[index].LAST_NAME,
                    RelationshipCode: vm.dependents[index].RELATIONSHIP_CODE
                };

                $q.all([
                    vm.getDropDependentModalPlansList(vm.dependents[index].ENROLLEE_ID),
                    vm.getDropDependentModalType(vm.dependents[index].ENROLLEE_ID)
                ]).then(function () {
                    openDropDependentModalLogic();
                });
            }
        };

        vm.getDropDependentModalPlansList = function (enrolleeId) {
            return EnrollmentSummaryService.getEnrolleePlans(enrolleeId).then(function (response) {
                vm.dropDependentModel.Plans = response.data;

                angular.forEach(vm.dropDependentModel.Plans, function (plan, key) {
                    plan.Selected = false;
                    plan.Description = plan.ProductName + ' (' + plan.LineOfBusinessDescription + ')';
                    plan.CustomId = 'plan_' + plan.PremiumGroupId + '_' + plan.ProductId;
                });
            });
        };

        vm.scrollTop = function (tag) {
            $('html, body').animate({ scrollTop: 0 }, 'slow');
        };


        Date.prototype.formatMMDDYYYY = function () {
            return (("0" + (this.getMonth() + 1)).slice(-2)) +
                "/" + ("0" + this.getDate()).slice(-2) +
                "/" + ("0" + this.getFullYear()).slice(-4);
        };

        vm.selectPCP = function (enrolleeData) {
            setPageTitle('Select Primary Care Provider');
            if (vm.mode == vm.eMode.VIEWING_DEPENDENT)
                window.location.href = '/FindAProvider/SelectPCP?enrolleeId=' + enrolleeData.ENROLLEE_ID;
            else
                window.location.href = '/FindAProvider/SelectPCP';
        };

        vm.getRequestTranslateObject = function () {
            if (vm.memberInfo === undefined) {
                return {};
            }
            else {
                var middleName = vm.memberInfo.MIDDLE_NAME !== null ? vm.memberInfo.MIDDLE_NAME + ' ' : '';
                return {
                    fullName: vm.memberInfo.FIRST_NAME + ' ' + middleName + vm.memberInfo.LAST_NAME
                };
            }
        };

        vm.goBack = function () {
            $window.location.href = '/MWP/EnrollmentSummary';
        }

        vm.isIndividualEnrollment = function (callback) {
            EnrollmentSummaryService.isIndividualEnrollment()
                .then(function successCallback(response) {
                    vm.isIndividualEnrollmentFlag = response.data;
                    if (callback && typeof callback === "function") callback();
                }, function errorCallback(response) {
                    console.error(response.Message);
                    console.error(response);
                    if ($scope.ExceptionDialogControl !== null) {
                        $scope.ExceptionDialogControl
                            .showDialog("Error retrieving member information.");
                    }
                });
        };

        vm.planAllowsDependents = function () {
            vm.planAllowsDependentsFlag = false;
            let policyHoldersCurrentActivePlanDTO = {
                enrolleeId: DataService.EnrolleeId,
                premiumGroupId: DataService.GroupId,
                productId: DataService.ProductId,
                spouseFlag: null,
                childCount: vm.getChildCountFromDependentsList(),
                dependentType: DataService.DependentType,
                subscriberId: vm.currentEnrollee.SUBSCRIBER_ID
            };
            EnrollmentSummaryService.canAddDependents(policyHoldersCurrentActivePlanDTO)
                .then(function successCallback(response) {
                    vm.hasSpouseFlag = response.data.hasSpouse;
                    vm.subscriberIsActiveFlag = response.data.subscriberIsActive;
                    vm.canAddSpouseFlag = response.data.canAddSpouse;
                    vm.canAddChildFlag = response.data.canAddChild;
                    if (vm.isIndividualEnrollmentFlag && DataService.HasAddDependentIndividualEnrollment) getEnrolleeDependents();

                    if (vm.hasSpouseFlag) {
                        vm.spouseTooltipMessage = "EnrollmentSummary_ActiveSpouse";
                    }
                    if (!vm.canAddSpouseFlag) {
                        vm.spouseTooltipMessage = "EnrollmentSummary_SpouseNoDependents";
                    }
                    if (!vm.canAddChildFlag) {
                        vm.childTooltipMessage = "EnrollmentSummary_ChildNoDependents";
                    }
                    if (vm.isNotMonthlyBillingCycleType() && !vm.isOpenEnrollmentFlag) {
                        let billingCycleValidationTooltipMessage = "AddDependents_BillingFrequencyValidation_Unable_Add_Dependents";

                        vm.spouseTooltipMessage = billingCycleValidationTooltipMessage;
                        vm.childTooltipMessage = billingCycleValidationTooltipMessage
                    }
                    if (!vm.subscriberIsActiveFlag) {
                        vm.spouseTooltipMessage = "EnrollmentSummary_SpouseNotActive";
                        vm.childTooltipMessage = "EnrollmentSummary_ChildNotActive";
                    }
                },
                    function errorCallback(response) {
                        if ($scope.ExceptionDialogControl !== null) {
                            $scope.ExceptionDialogControl
                                .showDialog("Error retrieving member information.");
                        }
                    });
        };

        vm.getChildCountFromDependentsList = function () {
            return DataService.Dependents.filter(function (dependent) {
                return dependent.RELATIONSHIP_CODE === RELATIONSHIP_CODE_CHILD && dependent.ENROLLMENT_STATUS_CODE === ACTIVE_DEPENDENT_CODE;
            }).length || 0;
        };

        vm.getQualifyingEventsRemoveDependent = function () {
            EnrollmentSummaryService.getQualifyingEventsRemoveDependent(vm.isOpenEnrollmentFlag)
                .then(function successCallback(response) {
                    vm.qualifyingEventList = response.data;

                    if (vm.isOpenEnrollmentFlag) {
                        vm.dropDependentModel.QualifyingEvent = vm.renewalPeriodChangeTerminationReasonCode;
                    }
                })
        };

        function openDropDependentModalLogic() {
            vm.dropDependentSuccessful = undefined;
            if (vm.activePlanExists) {
                vm.dropDependentBillingFrequencyError = undefined;
                vm.dropDependentModalStep = DROP_DEPENDENT_MODAL_STEP_1;
                vm.dropDependentFormValidations = {};
                vm.getQualifyingEventsRemoveDependent();
            }
            if (!vm.activePlanExists && vm.amountOfPlans > 1) {
                vm.dropDependentModalStep = DROP_DEPENDENT_MODAL_STEP_1;
                vm.dropDependentFormValidations = {};
            }
            if (!vm.activePlanExists && vm.amountOfPlans == 1) {
                vm.dropDependentModalStep = DROP_DEPENDENT_MODAL_STEP_2;
                var dependent = {
                    EnrolleeId: vm.dropDependentModel.EnrolleeId,
                    EventDate: null,
                    Plans: vm.dropDependentModel.Plans,
                    EnrolleeType: vm.dropDependentModel.RelationshipCode,
                    PremiumGroupId: DataService.GroupId,
                    BillingCycle: vm.billingCycleType,
                    BillingCycleName: vm.billingCycleTypeName,
                    TerminateReasonCode: null
                };
                EnrollmentSummaryService.validateDropDependent(dependent)
                    .then(function (response) {
                        const dateReason = "date";
                        const noPremiumRateReason = "noPremiumRate";
                        vm.dropDependentModel.PlansToNotDrop = response.data.PlansToNotDrop;
                        vm.dropDependentModel.PlansToDrop = response.data.PlansToDrop;
                        vm.dropDependentModel.TerminationDate = response.data.TerminationDate;
                        vm.dropDependentModel.NewPrice = response.data.NewPrice;

                        if (vm.dropDependentModel.PlansToNotDrop.length > 0) {
                            vm.plansToNotDropString = "";
                            vm.plansToNotDropCombinationString = "";
                            for (var i = 0; i < vm.dropDependentModel.PlansToNotDrop.length; i++) {
                                if (vm.dropDependentModel.PlansToNotDrop[i].ReasonToNotDrop === dateReason) {
                                    vm.plansToNotDropString += vm.dropDependentModel.PlansToNotDrop[i].Description + ", ";
                                } else if (vm.dropDependentModel.PlansToNotDrop[i].ReasonToNotDrop === noPremiumRateReason) {
                                    vm.plansToNotDropCombinationString += vm.dropDependentModel.PlansToNotDrop[i].Description + ", ";
                                }
                            }
                            vm.plansToNotDropString = vm.plansToNotDropString.substr(0, vm.plansToNotDropString.length - 2);
                            vm.plansToNotDropCombinationString = vm.plansToNotDropCombinationString.substr(0, vm.plansToNotDropCombinationString.length - 2);
                            if (vm.plansToNotDropString !== "") {
                                vm.dropDependentModalCustomWarning = {
                                    Message: "EnrollmentSummary_DropDependentModal_Exceeded_Term_Date"
                                };
                            }
                            if (vm.plansToNotDropCombinationString !== "") {
                                vm.dropDependentModalCustomWarningCombination = {
                                    Message: "EnrollmentSummary_DropDependentModal_PlanDoesNotSupport_NewCombination"
                                };
                            }
                        }

                        if (vm.dropDependentModel.PlansToDrop.length > 0) {
                            vm.plansToDropString = "";
                            for (var i = 0; i < vm.dropDependentModel.PlansToDrop.length; i++) {
                                vm.plansToDropString += vm.dropDependentModel.PlansToDrop[i].Description + ", ";
                            }
                            vm.plansToDropString = vm.plansToDropString.substr(0, vm.plansToDropString.length - 2);
                        }
                    }, function (response) {
                        if (response.errors.Error_QualifyingDateInvalid) {
                            if (response.errors.Error_QualifyingDateInvalid[0] === QUALIFYING_EVENT_DATE_PAST) {
                                vm.dropDependentModalCustomError = {
                                    Message: response.errors.Error_QualifyingDateInvalid[0],
                                    ExtraData: response.errors.Data_QualifyingDateInvalid[0],
                                    Params: { voicePhone: vm.voicePhone, email: vm.customerServiceEmail }
                                };
                                vm.dropDependentFormValidations.QualifyingEventDatePast = true;
                                vm.dropDependentFormValidations.EventDateTextBoxInvalid = true;
                                return;
                            }

                            if (response.errors.Error_QualifyingDateInvalid[0] === QUALIFYING_EVENT_DATE_FUTURE) {
                                vm.dropDependentFormValidations.Invalid = true;
                                vm.dropDependentFormValidations.QualifyingEventDateFuture = true;
                                vm.dropDependentFormValidations.EventDateTextBoxInvalid = true;
                                return;
                            }
                        }
                    });
            }
            vm.showDropDependentModalDialog();
        }

        function dropDependentCheckPlans() {
            vm.dropDependentFormValidations.plansRequired = false;
            if (!_.find(vm.dropDependentModel.Plans, function (obj) { return obj.Selected; })) {
                vm.dropDependentFormValidations.plansRequired = true;
                vm.dropDependentFormValidations.Invalid = true;
            }
        }

        function dropDependentCheckDocuments() {
            vm.dropDependentFormValidations.documentsRequired = false;
            if (vm.dropDependentModalDocuments.length === 0) {
                vm.dropDependentFormValidations.documentsRequired = true;
                vm.dropDependentFormValidations.Invalid = true;
            }
        }



        vm.eventDateValidation = function () {
            if (!vm.dropDependentForm.$submitted)
                return;

            if (vm.dropDependentForm.$invalid || vm.dropDependentFormValidations.Invalid) {
                vm.dropDependentFormErrors = wbxListErrorsService.getErrorListForBanner(vm.dropDependentForm);
                return;
            }
        }

        vm.validateRemoveDependent = function () {
            vm.dropDependentModalCustomError = undefined;
            vm.dropDependentModalCustomWarning = undefined;
            vm.dropDependentModalCustomWarningCombination = undefined;
            vm.dropDependentFormValidations = {};
            vm.dropDependentFormErrors = undefined;
            vm.dropDependentBillingFrequencyError = undefined;

            dropDependentCheckPlans();

            if (vm.dropDependentFormValidations.Invalid) return;

            if (vm.dropDependentModel.QualifyingEvent === vm.renewalPeriodChangeTerminationReasonCode) {
                vm.dropDependentModel.EventDate = new Date(new Date().getFullYear(), new Date().getMonth(), new Date().getDate());
            }

            if (vm.dropDependentModel.QualifyingEvent !== undefined && vm.dropDependentModel.QualifyingEvent !== vm.renewalPeriodChangeTerminationReasonCode) {
                dropDependentCheckDocuments();

                if (vm.dropDependentForm.$invalid || vm.dropDependentFormValidations.Invalid) {
                    vm.dropDependentFormErrors = wbxListErrorsService.getErrorListForBanner(vm.dropDependentForm);
                    return;
                }
            } else if (vm.dropDependentFormValidations.plansRequired && vm.dropDependentFormValidations.Invalid) {
                return;
            }


            var selectedPlans = "";
            var selectedPlansList = [];
            for (var i = 0; i < vm.dropDependentModel.Plans.length; i++) {
                if (vm.dropDependentModel.Plans[i].Selected) {
                    selectedPlans += vm.dropDependentModel.Plans[i].Description + ", ";
                    selectedPlansList.push(vm.dropDependentModel.Plans[i]);
                }
            }
            vm.dropDependentModel.SelectedPlans = selectedPlans.substr(0, selectedPlans.length - 2);

            var dependent = {
                EnrolleeId: vm.dropDependentModel.EnrolleeId,
                EventDate: vm.dropDependentModel.EventDate,
                Plans: selectedPlansList,
                EnrolleeType: vm.dropDependentModel.RelationshipCode,
                PremiumGroupId: DataService.GroupId,
                BillingCycle: vm.billingCycleType,
                BillingCycleName: vm.billingCycleTypeName,
                TerminateReasonCode: vm.dropDependentModel.QualifyingEvent
            };
            EnrollmentSummaryService.validateDropDependent(dependent)
                .then(function (response) {
                    const dateReason = "date";
                    const noPremiumRateReason = "noPremiumRate";
                    vm.dropDependentModel.PlansToNotDrop = response.data.PlansToNotDrop;
                    vm.dropDependentModel.PlansToDrop = response.data.PlansToDrop;
                    vm.dropDependentModel.TerminationDate = response.data.TerminationDate;
                    vm.dropDependentModel.NewPrice = response.data.NewPrice;

                    EnrollmentSummaryService.isCurrentDateAfter19thOfTheLastMonthFromCurrentContract({ isOpenEnrollment: vm.isOpenEnrollmentFlag, qualifyingEvent: vm.dropDependentModel.QualifyingEvent, effectiveDate: response.data.EffectiveDate === undefined ? null : response.data.EffectiveDate })
                        .then(function (response) {
                            vm.isCurrentDateAfter19thOfTheLastMonthFromCurrentContract = response;
                            vm.billingCycleType = response.billingCycleType;

                            if (vm.isNotMonthlyBillingCycleType() && vm.dropDependentModel.QualifyingEvent !== vm.renewalPeriodChangeTerminationReasonCode) {
                                vm.dropDependentBillingFrequencyError = {
                                    Message: 'DropDependents_BillingFrequencyValidation_Unable_Drop_Dependents',
                                    Params: {
                                        voicePhone: DataService.PortalInfo.VoicePhone,
                                        email: DataService.PortalInfo.CustomerServiceEmail
                                    }
                                };
                                return;
                            }

                            if (vm.dropDependentModel.PlansToNotDrop.length > 0) {
                                vm.plansToNotDropString = "";
                                vm.plansToNotDropCombinationString = "";
                                for (var i = 0; i < vm.dropDependentModel.PlansToNotDrop.length; i++) {
                                    if (vm.dropDependentModel.PlansToNotDrop[i].ReasonToNotDrop === dateReason) {
                                        vm.plansToNotDropString += vm.dropDependentModel.PlansToNotDrop[i].Description + ", ";
                                    } else if (vm.dropDependentModel.PlansToNotDrop[i].ReasonToNotDrop === noPremiumRateReason) {
                                        vm.plansToNotDropCombinationString += vm.dropDependentModel.PlansToNotDrop[i].Description + ", ";
                                    }
                                }
                                vm.plansToNotDropString = vm.plansToNotDropString.substr(0, vm.plansToNotDropString.length - 2);
                                vm.plansToNotDropCombinationString = vm.plansToNotDropCombinationString.substr(0, vm.plansToNotDropCombinationString.length - 2);
                                if (vm.plansToNotDropString !== "") {
                                    vm.dropDependentModalCustomWarning = {
                                        Message: "EnrollmentSummary_DropDependentModal_Exceeded_Term_Date"
                                    };
                                }
                                if (vm.plansToNotDropCombinationString !== "") {
                                    vm.dropDependentModalCustomWarningCombination = {
                                        Message: "EnrollmentSummary_DropDependentModal_PlanDoesNotSupport_NewCombination"
                                    };
                                }
                            }

                            if (vm.dropDependentModel.PlansToDrop.length > 0) {
                                vm.plansToDropString = "";
                                for (var i = 0; i < vm.dropDependentModel.PlansToDrop.length; i++) {
                                    vm.plansToDropString += vm.dropDependentModel.PlansToDrop[i].Description + ", ";
                                }
                                vm.plansToDropString = vm.plansToDropString.substr(0, vm.plansToDropString.length - 2);
                                vm.dropDependentModalStep = DROP_DEPENDENT_MODAL_STEP_2;
                            }
                        });
                }, function (response) {
                    if (response.errors.Error_QualifyingDateInvalid) {
                        if (response.errors.Error_QualifyingDateInvalid[0] === QUALIFYING_EVENT_DATE_PAST) {
                            vm.dropDependentModalCustomError = {
                                Message: response.errors.Error_QualifyingDateInvalid[0],
                                ExtraData: response.errors.Data_QualifyingDateInvalid[0],
                                Params: { voicePhone: vm.voicePhone, email: vm.customerServiceEmail }
                            };
                            vm.dropDependentFormValidations.QualifyingEventDatePast = true;
                            vm.dropDependentFormValidations.EventDateTextBoxInvalid = true;
                            return;
                        }

                        if (response.errors.Error_QualifyingDateInvalid[0] === QUALIFYING_EVENT_DATE_FUTURE) {
                            vm.dropDependentFormValidations.Invalid = true;
                            vm.dropDependentFormValidations.QualifyingEventDateFuture = true;
                            vm.dropDependentFormValidations.EventDateTextBoxInvalid = true;
                            return;
                        }
                    }
                });
        };

        vm.removeDependent = function () {
            var documentIds = [];
            var products = [];

            for (var i = 0; i < vm.dropDependentModalDocuments.length; i++) {
                documentIds.push(vm.dropDependentModalDocuments[i].documentId);
            }
            for (var j = 0; j < vm.dropDependentModel.PlansToDrop.length; j++) {
                products.push({
                    ProductId: vm.dropDependentModel.PlansToDrop[j].ProductId,
                    EffectiveDate: vm.dropDependentModel.PlansToDrop[j].EffectiveDate
                });
            }

            var dependent = {
                EventDate: vm.dropDependentModel.EventDate,
                EnrolleeId: vm.dropDependentModel.EnrolleeId,
                ReasonCode: vm.dropDependentModel.QualifyingEvent,
                DocumentIds: documentIds,
                Products: products,
                IsOpenEnrollment: vm.isOpenEnrollmentFlag,
                BillingCycleType: vm.billingCycleType
            };

            if (vm.dropDependentModel.QualifyingEvent === vm.renewalPeriodChangeTerminationReasonCode) {
                dependent.EventDate = new Date(new Date().getFullYear(), new Date().getMonth(), new Date().getDate());
                dependent.DocumentIds = null;
            }

            EnrollmentSummaryService.dropDependent(dependent)
                .then(function (response) {
                    vm.dependents = response;
                    vm.dropDependentSuccessful = true;
                    vm.closeDropDependentModalDialog();
                });
        };

        vm.setEnrolleeDependentValidation = function (enrolleeDependent) {
            return (enrolleeDependent.isSubscriberInactive && !vm.subscriberIsActiveFlag) ||
                (!enrolleeDependent.isOther && enrolleeDependent.isSpouse && !enrolleeDependent.canAddSpouse) ||
                (!enrolleeDependent.isOther && !enrolleeDependent.isSpouse && !enrolleeDependent.canAddChild) ||
                (enrolleeDependent.isOther && (!enrolleeDependent.canAddSpouse || !enrolleeDependent.canAddChild)) ||
                enrolleeDependent.existingSpouse ||
                enrolleeDependent.tooOldChild ||
                (vm.isNotMonthlyBillingCycleType() && !vm.isOpenEnrollmentFlag);
        };

        vm.canDropDependent = function (dependent) {
            if (dependent.RELATIONSHIP_CODE === RELATIONSHIP_CODE_CHILD && (dependent.ENROLLMENT_STATUS_CODE === ACTIVE_DEPENDENT_CODE || dependent.ENROLLMENT_STATUS_CODE === FUTURE_DEPENDENT_CODE)) {
                if (!vm.canDropChildFlag) {
                    return false
                }
            }
            if ((dependent.RELATIONSHIP_CODE === RELATIONSHIP_CODE_SPOUSE || dependent.RELATIONSHIP_CODE === RELATIONSHIP_CODE_LIFE_PARTNER) && (dependent.ENROLLMENT_STATUS_CODE === ACTIVE_DEPENDENT_CODE || dependent.ENROLLMENT_STATUS_CODE === FUTURE_DEPENDENT_CODE)) {
                if (!vm.canDropSpouseFlag) {
                    return false
                }
            }
            return true;
        };

        vm.canDropDependents = function () {
            let policyHoldersCurrentActivePlanDTO = {
                enrolleeId: DataService.EnrolleeId,
                premiumGroupId: DataService.GroupId,
                productId: DataService.ProductId,
                spouseFlag: null,
                childCount: vm.getChildCountFromDependentsList(),
                dependentType: DataService.DependentType,
                subscriberId: vm.currentEnrollee.SUBSCRIBER_ID
            };
            EnrollmentSummaryService.canDropDependents(policyHoldersCurrentActivePlanDTO)
                .then(function successCallback(response) {
                    vm.hasSpouseFlag = response.hasSpouse;
                    vm.subscriberIsActiveFlag = response.subscriberIsActive;
                    vm.canDropSpouseFlag = response.canDropSpouse;
                    vm.canDropChildFlag = response.canDropChild;
                },
                    function errorCallback(response) {
                        console.log("Error calling CanDropDependents: " + response);
                    });
        };

        function getEnrolleeDependents() {
            var enrolleeDependentsInputDTO = {
                premiumGroupId: DataService.GroupId,
                productId: DataService.ProductId,
                hasSpouseFlag: vm.hasSpouseFlag,
                canAddSpouseFlag: vm.canAddSpouseFlag,
                canAddChildFlag: vm.canAddChildFlag
            };
            EnrollmentSummaryService.getEnrolleeDependents(enrolleeDependentsInputDTO)
                .then(function successCallback(response) {
                    if (response === null || response.data === null) {
                        vm.enrolleeDependent.dependents = undefined;
                        return;
                    }
                    vm.enrolleeDependent.dependentAgeCutoff = response.data.dependentAgeCutoff;
                    vm.hasSpouseOnOtherPlansFlag = false;
                    vm.enrolleeDependent.dependents = response.data.dependents.map(function (enrolleeDependent) {
                        enrolleeDependent.fullName = enrolleeDependent.firstName;
                        enrolleeDependent.fullName += " ";
                        enrolleeDependent.fullName += enrolleeDependent.lastName;
                        enrolleeDependent.title = (enrolleeDependent.isSubscriberInactive && !vm.subscriberIsActiveFlag) ? "EnrollmentSummary_Enroll_SpouseChildCannotBeAdded" : !enrolleeDependent.isOther && enrolleeDependent.isSpouse && !enrolleeDependent.canAddSpouse ? "EnrollmentSummary_Enroll_SpouseCannotBeAddedPlanDoesNotAllowDependents" : !enrolleeDependent.isOther && !enrolleeDependent.isSpouse && !enrolleeDependent.canAddChild ? "EnrollmentSummary_Enroll_ChildCannotBeAdded" : enrolleeDependent.isOther && (!enrolleeDependent.canAddSpouse || !enrolleeDependent.canAddChild) ? "EnrollmentSummary_Enroll_DependentCannotBeAdded" : enrolleeDependent.existingSpouse ? "EnrollmentSummary_Enroll_SpouseCannotBeAdded" : enrolleeDependent.tooOldChild ? "EnrollmentSummary_Enroll_CannotEnrollDependent" : (vm.isNotMonthlyBillingCycleType() && !vm.isOpenEnrollmentFlag) ? "AddDependents_BillingFrequencyValidation_Unable_Add_Dependents" : "";
                        if (enrolleeDependent.isSpouse && enrolleeDependent.isActiveAnotherPlan) vm.hasSpouseOnOtherPlansFlag = true;
                        return enrolleeDependent;
                    });

                    if (vm.hasSpouseOnOtherPlansFlag && vm.spouseTooltipMessage === undefined) {
                        vm.spouseTooltipMessage = "EnrollmentSummary_ActiveSpouse";
                    }
                })
        }

        function getPlansTranslationParams() {
            return { plans: vm.plansToNotDropString };
        }

        function getCantDropPlansCombinationTranslationParams() {
            return { plans: vm.plansToNotDropCombinationString, voicePhone: vm.voicePhone, email: vm.customerServiceEmail };
        }

        function showDropDependentButton(statusCode) {
            return vm.isIndividualEnrollmentFlag && (statusCode == ACTIVE_DEPENDENT_CODE || statusCode == FUTURE_DEPENDENT_CODE)
        }

        function isNotMonthlyBillingCycleType() {
            const MONTHLY_BILLING_CYCLE_TYPE = 1;
            return !(vm.billingCycleType === MONTHLY_BILLING_CYCLE_TYPE);
        }

        function getDropDependentTooltipText(dependent) {
            if (isNotMonthlyBillingCycleType() && !vm.isOpenEnrollmentFlag) {
                return $translate.instant('DropDependents_BillingFrequencyValidation_Unable_Drop_Dependents', { voicePhone: vm.voicePhone, email: vm.customerServiceEmail })
            } else {
                if (!vm.canDropDependent(dependent)) {
                    return $translate.instant('DropDependents_PremiumRateValidation_Unable_Drop_Dependents')
                }
                return '';
            }
        }

        function getQualifyingEventsForAddDependentToPlan() {
            EnrollmentSummaryService.getAddReasonCodesForDependent(vm.isOpenEnrollmentFlag)
                .then(function successCallback(response) {
                    vm.qualifyingEventListForAddDependentToPlan = response.data;

                    if (vm.isOpenEnrollmentFlag) {
                        vm.addDependentToPlanModel.QualifyingEvent = vm.renewalPeriodChangeAddReasonCode;
                    }
                });
        }

        vm.openAddExistingDependentToPlanModal = function (enrolleeDependent) {
            if (vm.addDependentToPlanForm !== undefined) {
                vm.addDependentToPlanForm.$submitted = false;
            }

            if (vm.addDependentToPlanFutureElegibilityForm !== undefined) {
                vm.addDependentToPlanFutureElegibilityForm.$submitted = false;
            }

            vm.customErrorMessageList = [];
            vm.addDependentBillingFrequencyError = undefined;
            vm.addDependentConfirmationDateError = undefined;
            vm.addDependentConfirmationCombinationError = undefined;

            if (vm.isFutureEligibility()) {
                vm.addDependentToPlanFutureElegibilityModel = {
                    fullName: enrolleeDependent.fullName,
                    plan: vm.genInfo.BENEFIT_PLAN,
                    firstName: enrolleeDependent.firstName,
                    lastName: enrolleeDependent.lastName,
                    dateOfBirth: enrolleeDependent.dateOfBirth,
                    EnrolleeId: enrolleeDependent.enrolleeId,
                    relationshipCode: enrolleeDependent.relationshipCode,
                    isEnroll: true
                };
                vm.addDependentToPlanFutureElegibilityFormValidations = {};
                vm.addDependentFutureEligibilityDateError = undefined;
                vm.addDependentFutureEligibilityCombinationError = undefined;

                validateAddDependentNewPrice();
            } else {
                vm.addDependentToPlanModalDocuments = [];
                vm.addDependentToPlanModel = {
                    firstName: enrolleeDependent.firstName,
                    lastName: enrolleeDependent.lastName,
                    dateOfBirth: enrolleeDependent.dateOfBirth,
                    EnrolleeId: enrolleeDependent.enrolleeId,
                    tooOldChild: enrolleeDependent.tooOldChild,
                    relationshipCode: enrolleeDependent.relationshipCode,
                    isEnroll: true
                };
                vm.addDependentToPlanFormValidations = {};
                getQualifyingEventsForAddDependentToPlan();
            }

            $('#AddExistingDependentToPlanModalDialog').modal({
                backdrop: 'static'
            });
            $('#AddExistingDependentToPlanModalDialog').modal('show');
        };

        vm.closeAddExistingDependentToPlanModalDialog = function () {
            vm.addDependentToPlanCustomError = undefined;
            vm.addDependentToPlanFormValidations = {};
            vm.addDependentToPlanFutureElegibilityFormValidations = {};

            if (vm.addDependentToPlanForm) {
                vm.addDependentToPlanForm.$setPristine(true);
                vm.addDependentToPlanForm.$setUntouched(true);
            }

            if (vm.addDependentToPlanFutureElegibilityForm) {
                vm.addDependentToPlanFutureElegibilityForm.$setPristine(true);
                vm.addDependentToPlanFutureElegibilityForm.$setUntouched(true);
            }

            $('#AddExistingDependentToPlanModalDialog').modal('hide');
        };

        function addDependentToPlanCheckDocuments() {
            vm.addDependentToPlanFormValidations.documentsRequired = false;
            if (vm.addDependentToPlanModalDocuments.length === 0) {
                vm.addDependentToPlanFormValidations.documentsRequired = true;
                vm.addDependentToPlanFormValidations.Invalid = true;
            }
        }

        vm.eventDateValidationForAddDependentToPlan = function () {
            if (!vm.addDependentToPlanForm.$submitted)
                return;

            if (vm.addDependentToPlanFormValidations.QualifyingEventDatePast) {
                vm.addDependentToPlanCustomError = undefined;
                vm.addDependentToPlanFormValidations.QualifyingEventDatePast = false;
                vm.addDependentToPlanFormValidations.EventDateTextBoxInvalid = false;
            }

            if (vm.addDependentToPlanFormValidations.DateBirthInvalid) {
                vm.addDependentToPlanCustomError = undefined;
                vm.addDependentToPlanFormValidations.DateBirthInvalid = false;
            }

            addDependentToPlanCheckBirthDate();

            if (vm.addDependentToPlanForm.$invalid || vm.addDependentToPlanFormValidations.Invalid) {
                vm.addDependentToPlanFormErrors = wbxListErrorsService.getErrorListForBanner(vm.addDependentToPlanForm);
                return;
            }
        }

        function addDependentToPlanCheckAgeCutoff() {
            if (vm.addDependentToPlanModel.tooOldChild) {
                vm.addDependentToPlanCustomError = {
                    Message: 'EnrollmentSummary_AddDependent_Validation_DependentMustBeYoungerThanAgeCutoff',
                    Params: {
                        dependentAgeCutoff: DataService.DependentAgeCutoff
                    }
                };
                vm.addDependentToPlanFormValidations.Invalid = true;
            }
        }

        function addDependentToPlanCheckBirthDate() {
            var eventDate = new Date(vm.addDependentToPlanModel.EventDate);
            var birthDate = new Date(vm.addDependentToPlanModel.dateOfBirth);

            if (vm.addDependentToPlanModel.QualifyingEvent === BIRTH_REASON_CODE &&
                eventDate.getTime() !== birthDate.getTime() &&
                !vm.addDependentToPlanForm.$invalid) {
                vm.addDependentToPlanCustomError = {
                    Message: QUALIFYING_EVENT_TYPE_BIRTH_DATE
                };
                vm.addDependentToPlanFormValidations.DateBirthInvalid = true;
            }
        }

        function concatenate(productList) {
            return productList.map(function (product) { return product.productDescription; }).join(", ");
        }

        function validatePlans(payload, callback) {
            let inputValidate = {
                eventDate: payload.addReasonEventDate,
                isFutureEligibility: payload.isFutureEligibility,
                subscriberEffectiveDate: payload.subscriberEffectiveDate,
                plans: payload.products,
                addReasonCode: payload.addReasonCode,
                EnrolleeType: vm.addDependentToPlanModel.relationshipCode,
                PremiumGroupId: DataService.GroupId,
                BillingCycle: vm.billingCycleType
            };
            EnrollmentSummaryService.validateAddDependent(inputValidate)
                .then(function (result) {
                    if (result.data.PlansCantAddDate.length > 0) {
                        vm.addDependentConfirmationDateError = {
                            Message: 'AddDependentModal_TerminationDateError',
                            Params: {
                                plansCantAddDate: concatenate(result.data.PlansCantAddDate)
                            }
                        };
                    }

                    if (result.data.PlansCantAddDependent.length > 0) {
                        vm.addDependentConfirmationCombinationError = {
                            Message: 'AddDependentModal_DependentCombinationError',
                            Params: {
                                plansCantAddDependent: concatenate(result.data.PlansCantAddDependent),
                                phone: vm.voicePhone,
                                email: vm.customerServiceEmail
                            }
                        };
                    }

                    payload.areSomePlansValid = result.data.PlansToAdd.length > 0;
                    callback(result);
                });
        }

        vm.validateAddDependentToPlan = function () {
            vm.addDependentToPlanCustomError = undefined;
            vm.addDependentToPlanFormErrors = undefined;
            vm.addDependentToPlanFormValidations = {};
            vm.customErrorMessageList = [];
            vm.addDependentBillingFrequencyError = undefined;
            vm.addDependentToPlanFormValidations.DateBirthInvalid = false;

            if (vm.addDependentToPlanModel.QualifyingEvent !== vm.renewalPeriodChangeAddReasonCode) {
                addDependentToPlanCheckDocuments();
                addDependentToPlanCheckAgeCutoff();
                addDependentToPlanCheckBirthDate();

                if (vm.addDependentToPlanForm.$invalid || vm.addDependentToPlanFormValidations.Invalid) {
                    vm.addDependentToPlanFormErrors = wbxListErrorsService.getErrorListForBanner(vm.addDependentToPlanForm);
                    return;
                }

                if (vm.addDependentToPlanFormValidations.DateBirthInvalid) {
                    return;
                }
            } else {
                vm.addDependentToPlanModel.EventDate = new Date(new Date().getFullYear(), new Date().getMonth(), new Date().getDate());
            }

            let products = [DataService.ProductId];

            const payload = {
                lastName: vm.addDependentToPlanModel.lastName,
                firstName: vm.addDependentToPlanModel.firstName,
                dateOfBirth: vm.addDependentToPlanModel.dateOfBirth,
                address1: DataService.GenInfo.ADDRESS1,
                address2: DataService.GenInfo.ADDRESS2,
                city: DataService.GenInfo.CITY,
                state: DataService.GenInfo.STATE,
                zip: DataService.GenInfo.ZIP,
                phone: DataService.GenInfo.PHONE_NUMBER,
                addReasonCode: vm.addDependentToPlanModel.QualifyingEvent,
                addReasonEventDate: vm.addDependentToPlanModel.EventDate,
                products: products.map(x => ({ productId: x, premiumGroupId: DataService.GroupId, productDescription: vm.genInfo.BENEFIT_PLAN })),
                relationshipCode: vm.addDependentToPlanModel.relationshipCode,
                documentIds: vm.addDependentToPlanModalDocuments.map(x => x.documentId),
                isFutureEligibility: vm.isFutureEligibility(),
                subscriberEffectiveDate: DataService.GenInfo.EFFECTIVE_DATE,
                isEnroll: vm.addDependentToPlanModel.isEnroll,
                isOpenEnrollment: vm.isOpenEnrollmentFlag,
                billingCycleType: vm.billingCycleType
            };

            if (vm.addDependentToPlanModel.QualifyingEvent === vm.renewalPeriodChangeAddReasonCode) {
                payload.documentIds = null;
            }

            validatePlans(payload, function (response) {
                EnrollmentSummaryService.isCurrentDateAfter19thOfTheLastMonthFromCurrentContract({ isOpenEnrollment: vm.isOpenEnrollmentFlag, qualifyingEvent: vm.addDependentToPlanModel.QualifyingEvent, effectiveDate: response.data.EffectiveDate === undefined ? null : response.data.EffectiveDate })
                    .then(function (response) {
                        vm.billingCycleType = response.billingCycleType;
                        vm.billingCycleTypeName = response.billingCycleTypeDescription;

                        if (vm.isNotMonthlyBillingCycleType() && vm.addDependentToPlanModel.QualifyingEvent !== vm.renewalPeriodChangeAddReasonCode) {
                            vm.addDependentBillingFrequencyError = {
                                Message: 'AddDependents_BillingFrequencyValidation_Unable_Add_Dependents',
                                Params: {
                                    billingFrequency: vm.billingCycleTypeName,
                                    customerServicePhone: DataService.PortalInfo.VoicePhone,
                                    customerServiceEmail: DataService.PortalInfo.CustomerServiceEmail
                                }
                            };
                            return;
                        }

                        if (payload.areSomePlansValid) {
                            $('#AddExistingDependentToPlanModalDialog').modal('hide');
                            openAddDependentConfirmationModal(payload);
                        }
                    });
            });
        };

        vm.changeQualifyingEvent = function () {
            vm.addDependentToPlanCustomError = undefined;
            vm.addDependentToPlanFormValidations = {};
            vm.addDependentBillingFrequencyError = undefined;

            if (vm.addDependentToPlanModel.QualifyingEvent === vm.renewalPeriodChangeAddReasonCode) {
                vm.addDependentToPlanForm.$setPristine(true);
                vm.addDependentToPlanForm.$setUntouched(true);
            }
        }

        function openAddDependentConfirmationModal(payload) {
            payload.subscriberId = vm.enrolleeId;
            var modalDefaults = {
                backdrop: 'static',
                keyboard: true,
                modalFade: true,
                component: 'addDependentConfirmationModalComponent',
                size: 'md',
                windowClass: "",
                resolve: {
                    payload: function () { return payload; }
                }
            };
            wbxModalService.showModal(modalDefaults, {}).then(function (response) {
                if (response.result === "submit") {
                    payload.products = response.data;
                    EnrollmentSummaryService.addDependent(payload)
                        .then(function (responseAddDependent) {
                            successfullyAddDependent(responseAddDependent);
                        }, function (data) {
                            $('#AddExistingDependentToPlanModalDialog').modal('show');
                            if (typeof (data.errors) !== 'object') return;
                            const errors = Object.keys(data.errors).map(errorKey => ({
                                messageTranslationKey: errorKey,
                                params: { voicePhone: DataService.get("PortalInfo")['VoicePhone'], email: DataService.get("PortalInfo")['CustomerServiceEmail'] },
                                extraInfo: data.errors[errorKey]
                            }))
                            vm.customErrorMessageList.push(...errors);
                        });
                }
            });
        }

        vm.isAddSpouseButtonDisabled = function () {
            return !vm.canAddSpouseFlag || !vm.subscriberIsActiveFlag || vm.hasSpouseFlag || vm.hasSpouseOnOtherPlansFlag || (vm.isNotMonthlyBillingCycleType() && !vm.isOpenEnrollmentFlag);
        };

        vm.isAddChildButtonDisabled = function () {
            return !vm.canAddChildFlag || !vm.subscriberIsActiveFlag || (vm.isNotMonthlyBillingCycleType() && !vm.isOpenEnrollmentFlag);
        };

        vm.isFutureEligibility = function () {
            return DataService.IsFutureEligibility;
        };

        vm.validateAddDependentToPlanFutureElegibility = function () {
            vm.addDependentToPlanCustomError = undefined;
            vm.addDependentToPlanFormValidations = {};
            vm.customErrorMessageList = [];
            vm.addDependentFutureEligibilityDateError = undefined;
            vm.addDependentFutureEligibilityCombinationError = undefined;

            let products = [DataService.ProductId];

            const payload = {
                lastName: vm.addDependentToPlanFutureElegibilityModel.lastName,
                firstName: vm.addDependentToPlanFutureElegibilityModel.firstName,
                dateOfBirth: vm.addDependentToPlanFutureElegibilityModel.dateOfBirth,
                address1: DataService.GenInfo.ADDRESS1,
                address2: DataService.GenInfo.ADDRESS2,
                city: DataService.GenInfo.CITY,
                state: DataService.GenInfo.STATE,
                zip: DataService.GenInfo.ZIP,
                phone: DataService.GenInfo.PHONE_NUMBER,
                addReasonCode: null,
                addReasonEventDate: null,
                products: products.map(x => ({ productId: x, premiumGroupId: DataService.GroupId })),
                relationshipCode: vm.addDependentToPlanFutureElegibilityModel.relationshipCode,
                documentIds: null,
                isFutureEligibility: vm.isFutureEligibility(),
                subscriberEffectiveDate: DataService.GenInfo.EFFECTIVE_DATE,
                isEnroll: vm.addDependentToPlanFutureElegibilityModel.isEnroll
            };

            validatePlansFutureEligibility(payload);
        };

        vm.openTerminateContractModal = function () {
            vm.terminateSubscriberSuccessful = undefined;

            var modalDefaults = {
                backdrop: 'static',
                keyboard: true,
                modalFade: true,
                component: 'terminateModalComponent',
                size: 'lg',
                windowClass: "",
                resolve: {
                    payload: { isComingFromOpenEnrollment: false }
                }
            };
            wbxModalService.showModal(modalDefaults, {});
        }

        vm.isTerminateButtonDisabled = function () {
            vm.terminateContractTooltipMessage = $translate.instant('EnrollmentSummary_Terminate');
            vm.terminateContractTooltipMessageMobile = 'EnrollmentSummary_Terminate';

            angular.element("#TerminateWithText > i").attr('title', vm.terminateContractTooltipMessage);
            angular.element("#TerminateWithText_Bottom > i").attr('title', vm.terminateContractTooltipMessage);

            if (vm.currentEnrollee.ENROLLMENT_STATUS_CODE !== ENROLLMENT_STATUS_CODE_ACTIVE) {
                vm.terminateContractTooltipMessage = $translate.instant('EnrollmentSummary_PolicyHolderValidation_Unable_Terminate');
                vm.terminateContractTooltipMessageMobile = 'EnrollmentSummary_PolicyHolderValidation_Unable_Terminate';

                angular.element("#TerminateWithText > i").attr('title', vm.terminateContractTooltipMessage);
                angular.element("#TerminateWithText_Bottom > i").attr('title', vm.terminateContractTooltipMessage);
                return true;
            }

            if (vm.isNotMonthlyBillingCycleType() && !vm.isOpenEnrollmentFlag) {
                vm.terminateContractTooltipMessage = $translate.instant('EnrollmentSummary_BillingFrequencyValidation_Unable_Terminate',
                    {
                        billingFrequency: vm.billingCycleTypeName,
                        customerServicePhone: DataService.PortalInfo.VoicePhone,
                        customerServiceEmail: DataService.PortalInfo.CustomerServiceEmail
                    })
                vm.terminateContractTooltipMessageMobile = 'EnrollmentSummary_BillingFrequencyValidation_Unable_Terminate';

                angular.element("#TerminateWithText > i").attr('title', vm.terminateContractTooltipMessage);
                angular.element("#TerminateWithText_Bottom > i").attr('title', vm.terminateContractTooltipMessage);
                return true;
            }

            return false;
        };

        vm.isIndividualEnrollmentPlan = function () {
            return DataService.IsIndividualEnrollmentPlan;
        };

        function validateOpenEnrollment(callback) {
            vm.isOpenEnrollmentFlag = false;
            openEnrollmentService.getIsOpenEnrollment()
                .then(function successCallback(response) {
                    if (response) {
                        vm.isOpenEnrollmentFlag = response.isOpenEnrollment;
                        if (callback && typeof callback === "function") callback();
                    }
                });
        }

        vm.openUpdateTierModal = function () {
            var modalDefaults = {
                backdrop: 'static',
                keyboard: true,
                modalFade: true,
                component: 'updateEscalationTierModalComponent',
                size: 'md',
                windowClass: "",
                resolve: {
                    params: () => ({
                        planName: vm.genInfo.BENEFIT_PLAN,
                        insuredEnrolleeId: DataService.EnrolleeId
                    })
                }
            };
            wbxModalService.showModal(modalDefaults, {})
                .then((response) => {
                    if (response.result !== 'success') return;
                    vm.displayCustomInfoBanner = true;
                    vm.customSuccessBannerTranslatedText = $translate.instant("EnrollmentSummary_EscalationTier_Upload_SuccessText")
                });
        }

        function changeQualifyingEventDropDependent() {
            vm.dropDependentModalCustomError = undefined;
            vm.dropDependentModalCustomWarning = undefined;
            vm.dropDependentModalCustomWarningCombination = undefined;
            vm.dropDependentFormValidations = {};
            vm.dropDependentFormErrors = undefined;
            vm.dropDependentBillingFrequencyError = undefined;

            if (vm.dropDependentForm && vm.dropDependentModel.QualifyingEvent === vm.renewalPeriodChangeTerminationReasonCode) {
                vm.dropDependentForm.$setPristine(true);
                vm.dropDependentForm.$setUntouched(true);
            }
        }

        function isDependentWithPhiFullAccess(dependent) {
            return dependent.AGE < 18 || (dependent.AGE >= 18 && !!dependent.PHI_FULL_ACCESS_FLAG);
        }

        function isDependentDisplayableWithoutPhiAccess(dependent) {
            return vm.isIndividualEnrollmentFlag || isDependentWithPhiFullAccess(dependent);
        }

        function getDependentOptionTooltip(dependent) {
            return isDependentWithPhiFullAccess(dependent)
                ? ''
                : $translate.instant('EnrollmentSummary_DependentList_OptionButton_DisabledByPhiAccess')
        }

        function canUpgradeBenefitTier() {
            const MAXIMUM_BENEFIT_TIER = vm.escalationTier.maximumEscalationTier || 4;
            return vm.escalationTier.benefitLevelEscalation < MAXIMUM_BENEFIT_TIER;
        }

        vm.getDropDependentModalType = function () {
            return EnrollmentSummaryService.getDropDependentInfo().then(function (response) {
                vm.amountOfPlans = response.amountOfPlans;
                vm.activePlanExists = response.activePlanExists;
            });
        };

        function validateAddDependentNewPrice() {
            let products = [DataService.ProductId];
            let inputValidate = {
                eventDate: null,
                isFutureEligibility: vm.isFutureEligibility(),
                subscriberEffectiveDate: DataService.GenInfo.EFFECTIVE_DATE,
                plans: products.map(x => ({ productId: x, premiumGroupId: DataService.GroupId })),
                addReasonCode: null,
                EnrolleeType: vm.addDependentToPlanFutureElegibilityModel.relationshipCode,
                PremiumGroupId: DataService.GroupId,
                BillingCycle: vm.billingCycleType
            };
            EnrollmentSummaryService.validateAddDependent(inputValidate)
                .then(function (result) {
                    vm.addDependentToPlanFutureElegibilityModel.newPrice = result.data.NewPrice;
                });
        }

        function validatePlansFutureEligibility(payload) {
            let inputValidate = {
                eventDate: payload.addReasonEventDate,
                isFutureEligibility: payload.isFutureEligibility,
                subscriberEffectiveDate: payload.subscriberEffectiveDate,
                plans: payload.products,
                addReasonCode: payload.addReasonCode,
                EnrolleeType: vm.addDependentToPlanFutureElegibilityModel.relationshipCode,
                PremiumGroupId: DataService.GroupId,
                BillingCycle: vm.billingCycleType
            };
            EnrollmentSummaryService.validateAddDependent(inputValidate)
                .then(function (result) {
                    if (result.data.PlansCantAddDate.length > 0) {
                        vm.addDependentFutureEligibilityDateError = {
                            Message: 'AddDependentFutureEligibility_TerminationDateError',
                            Params: {
                                plansCantAddDate: concatenate(result.data.PlansCantAddDate)
                            }
                        };
                    }

                    if (result.data.PlansCantAddDependent.length > 0) {
                        vm.addDependentFutureEligibilityCombinationError = {
                            Message: 'AddDependentFutureEligibility_DependentCombinationError',
                            Params: {
                                plansCantAddDependent: concatenate(result.data.PlansCantAddDependent),
                                phone: result.data.Phone,
                                email: result.data.Email
                            }
                        };
                    }

                    if (result.data.PlansToAdd.length > 0) {
                        EnrollmentSummaryService.addDependent(payload)
                            .then(function (response) {
                                successfullyAddDependent(response);
                            }, function (data) {
                                if (typeof (data.errors) !== 'object') return;
                                const errors = Object.keys(data.errors).map(errorKey => ({
                                    messageTranslationKey: errorKey,
                                    params: { voicePhone: DataService.get("PortalInfo")['VoicePhone'], email: DataService.get("PortalInfo")['CustomerServiceEmail'] },
                                    extraInfo: data.errors[errorKey]
                                }))
                                vm.customErrorMessageList.push(...errors);
                            });
                    }
                });
        }

        function successfullyAddDependent(response) {
            vm.closeAddExistingDependentToPlanModalDialog();
            getEnrolleeDependents();
            vm.addSaveSuccessful = true;
            vm.dependents = response.data.dependents;
            vm.isIndividualEnrollment(function () {
                vm.planAllowsDependents();
            });
            vm.canDropDependents();
        }

        $scope.$on('terminateSubscriber', function (event, responseTerminateSubscriber) {
            vm.terminateSubscriberSuccessful = responseTerminateSubscriber.IsSusbcriberTerminate;

            if (vm.terminateSubscriberSuccessful) {
                getEnrolleeDependents();
                vm.dependents = responseTerminateSubscriber.Dependents;
                vm.genInfo = responseTerminateSubscriber.GeneralInfo;
                setupCurrentEnrollee(responseTerminateSubscriber.GeneralInfo);
                vm.isIndividualEnrollment(function () {
                    vm.planAllowsDependents();
                });
                vm.canDropDependents();
            }
        })

        function setupCurrentEnrollee(generalInfo) {
            vm.genInfo.CAN_LOGIN = true;
            vm.genInfo.LAST_4_SSN = vm.genInfo !== null && vm.genInfo.LAST_4_SSN !== null
                ? vm.genInfo.LAST_4_SSN.trim()
                : "";

            if ($stateParams.data === undefined)
                vm.genInfo.ENROLLEE_ID = DataService.EnrolleeId;

            vm.currentEnrollee = generalInfo;
        }

  

        vm.closeBenefitSummaryModal = function () {
            vm.clearCodeSearchResults();
            $('#BenefitSummaryReportModal').modal('hide');
        }

        vm.loadBenefitSummaryReportData = function () {
            vm.loadingCoinsurance = true;  
            vm.loadingForPrint = false;
            let productId = parseInt(DataService.ProductId);
            productId = isNaN(productId) ? 0 : productId; 

            let promise = vm.getBenefitSummaryreportData(productId);
            promise.then(function (r) {
                let memberData = vm.GetBenefitSummaryreportMemberHeaderData(productId);
                memberData.then(function () {
                    let coninsuranceData = vm.getBenefitSummaryCoinsurance(vm.currentProductPeriod, productId);
                    coninsuranceData.then(function () {
                        let productPeriodData = vm.getBenefitSummaryCopayAmounts(vm.currentProductPeriod, productId);
                        productPeriodData.then(function () {
                            vm.resetBenefitSummaryModal();
                            vm.loadingCoinsurance = false;
                        });

                    });
                });
            });
        }
        vm.clearCodeSearchResults = function () {
            vm.searchCode = '';
            vm.codeSearchForm.$invalid = false;
            vm.codeSearchForm.$submitted = false;
            vm.codeSearchResult = [];
            vm.hasCodesets = false;
            vm.hasSearchResults = false;
        }

        vm.changeIconOnClick = function (data) {
            data.collapsed = !data.collapsed;
            $('#' + this.id).on('shown.bs.collapse',
                function () {
                    $(this).parent().find('.panel-heading').addClass('panel-heading-opened');
                    $(this).parent().find(".fa-caret-right").removeClass("fa-caret-right")
                        .addClass("fa-caret-up");
                }).on('hidden.bs.collapse',
                    function () {
                        $(this).parent().find('.panel-heading').removeClass('panel-heading-opened');
                        $(this).parent().find(".fa-caret-up").removeClass("fa-caret-up").addClass("fa-caret-right");
                    });
        }

        vm.getBenefitSummaryreportData = function (productId) {
            vm.benefitSummaryDataOON = [];
            var deferred = $q.defer();

            $http({
                method: 'GET',
                url: '/BenefitSummaryReport/GetBenefitSummaryReport',
                params: {
                    productId: productId,
                    enrolleeId: parseInt(vm.benefitSummaryEnrolleeId)
                }
            }).then(function (data) {
                vm.benefitSummaryData = data.data;
                if (vm.benefitSummaryData.length > 0) {
                    angular.copy(vm.benefitSummaryData, vm.benefitSummaryDataOON);
                    vm.benefitSummaryDataOON = vm.benefitSummaryDataOON.filter(function (item) { return item.OON_FLAG == 1 });
                    vm.benefitSummaryData = vm.benefitSummaryData.filter(function (item) { return item.OON_FLAG == 0 });
                }
                deferred.resolve(true);
            });
            return deferred.promise;
        }

        vm.GetBenefitSummaryreportMemberHeaderData = function (productId) {
            vm.ELIGIBLE = 1;
            vm.NOT_ELIGIBLE = 2;
            vm.ELIGIBLE_STARTING = 3;
            vm.ELIGIBLE_ENDING = 4;

            var deferred = $q.defer();
            vm.benefitSummaryMemberHeaderData = [];

            var today = moment().format("MM/DD/yyyy");
            $http({
                method: 'GET',
                url: '/BenefitSummaryReport/GetBenefitSummaryReportMemberData',
                params: {
                    productId: productId,
                    enrolleeId: parseInt(vm.benefitSummaryEnrolleeId),
                    dateOfService: today
                }
            }).then(function (data) {
                vm.benefitSummaryMemberHeaderData = data.data;
                vm.currentProductPeriod = vm.benefitSummaryMemberHeaderData.PRODUCT_PERIOD;
                deferred.resolve(true);
            });
            vm.clearCodeSearchResults();
            return deferred.promise;
        }
       
        vm.getCoveredServices = function () {
            var deferred = $q.defer();
            vm.benefitSummaryCoveredServicesData = [];
            var today = moment().format("MM/DD/yyyy");
            $http({
                method: 'GET',
                url: '/BenefitSummaryReport/GetBenefitSummaryCoveredServices',
                params: {
                    productId: parseInt(DataService.ProductId),
                    enrolleeId: parseInt(vm.benefitSummaryEnrolleeId),
                    dateOfService: today
                }
            }).then(function (data) {
                vm.benefitSummaryCoveredServicesData = data.data;

                deferred.resolve(true);
            });

            return deferred.promise;
        }
        vm.procedureCodeSearch = function (productCode) {
  
            vm.codeSearchResult = [];
            vm.invalidCode = false;
            vm.hasSearchResults = false;
            vm.hasCodesets = false;
            vm.codeSearchForm.$submitted = true;
            var today = moment().format("MM/DD/yyyy");

            if (vm.codeSearchForm.$invalid || productCode.length < 5) {
                vm.searchCode = '';
                return false;
            }
            $http({
                method: 'GET',
                url: '/BenefitSummaryReport/BenefitSummaryCodeSearch',
                params: {
                    productId: parseInt(DataService.ProductId),
                    benefitLevel: null,
                    enrolleeId: vm.selectedEnrolleeId,
                    dateOfService: today,
                    code: productCode
                }
            }).then(function (data) {
                vm.codeSearchResult = data.data;
                vm.hasSearchResults = vm.codeSearchResult.length > 0;
                vm.hasCodesets = false;
                var hasCodeset = vm.codeSearchResult.map(function (item, index) {
                    if (item.CODESET_DESCRIPTION.length > 0) {
                        vm.hasCodesets = true;
                    }
                    if (item.DESCRIPTION == '- Invalid Code -') {
                        vm.invalidCode = true;
                    }
                });
            });
        }
  

        vm.getBenefitSummaryCoinsurance = function (productPeriod, productId) {
            vm.benefitSummaryCoinsuranceData = [];
            vm.benefitSummaryCoinsuranceDataOON = [];
            vm.coinsuranceCodeGroups = [];
            vm.coinsuranceCodeGroupsOOA = [];
            vm.hasCoinsurance = false;
            vm.hasCoinsuranceOON = false;

            var deferred = $q.defer();
            
            $http({
                method: 'GET',
                url: '/BenefitSummaryReport/GetBenefitSummaryReportCoinsuranceData',
                params: {
                    productId: productId,
                    productPeriod: productPeriod
                }
            }).then(function (data) {
                vm.benefitSummaryCoinsuranceData = data.data;
                if (vm.benefitSummaryCoinsuranceData.length > 0) {
                    angular.copy(vm.benefitSummaryCoinsuranceData, vm.benefitSummaryCoinsuranceDataOON);
                    vm.benefitSummaryCoinsuranceDataOON = vm.benefitSummaryCoinsuranceDataOON.filter(function (item) { return item.OON_FLAG == 1 });
                    vm.benefitSummaryCoinsuranceData = vm.benefitSummaryCoinsuranceData.filter(function (item) { return item.OON_FLAG == 0 });

                    if (vm.benefitSummaryCoinsuranceData.length > 0) {
                        vm.coinsuranceCodeGroups = vm.benefitSummaryCoinsuranceData.reduce((acc, cur) => [
                            ...acc.filter((obj) => obj.CODE_GROUP !== cur.CODE_GROUP), cur
                        ], []);
                    }

                    if (vm.benefitSummaryCoinsuranceDataOON.length > 0) {
                        vm.coinsuranceCodeGroupsOOA = vm.benefitSummaryCoinsuranceDataOON.reduce((acc, cur) => [
                            ...acc.filter((obj) => obj.CODE_GROUP !== cur.CODE_GROUP), cur
                        ], []);
                    }
                }
                vm.hasCoinsurance = vm.benefitSummaryCoinsuranceData.length > 0;;
                vm.hasCoinsuranceOON = vm.benefitSummaryCoinsuranceDataOON.length > 0;;
                deferred.resolve(true);
            });

            return deferred.promise;
        }

        vm.getServiceLimitations = function () {
            var promise = vm.getServiceLimitationsData();
            promise.then(function (r) {
                vm.getBenefitSummaryWaitingPeriods();
            });
        }

        vm.getServiceLimitationsData = function () {

            var deferred = $q.defer();
            var LIMITATION_BY_CODE = 1;
            var LIMITATION_BY_CODESET = 3;
            vm.benefitSummaryServiceLimitations = [];
            vm.serviceLimitationsByCode = [];
            vm.serviceLimitationsByCodeSet = [];
            vm.serviceLimitationsByAge = [];
            var deferred = $q.defer();
            let productId = parseInt(DataService.ProductId);
            productId = isNaN(productId) ? 0 : productId;

            $http({
                method: 'GET',
                url: '/BenefitSummaryReport/GetBenefitSummaryServiceLimitationsData',
                params: {
                    productId: productId,
                    enrolleeId: parseInt(vm.benefitSummaryEnrolleeId),
                }
            }).then(function (data) {
                vm.benefitSummaryServiceLimitations = data.data;
                angular.copy(vm.benefitSummaryServiceLimitations, vm.serviceLimitationsByCode);
                angular.copy(vm.benefitSummaryServiceLimitations, vm.serviceLimitationsByCodeSet);
                vm.serviceLimitationsByCode = vm.serviceLimitationsByCode.filter(function (item) { return item.LIMITATION_TYPE == LIMITATION_BY_CODE });
                vm.serviceLimitationsByCodeSet = vm.serviceLimitationsByCodeSet.filter(function (item) { return item.LIMITATION_TYPE == LIMITATION_BY_CODESET });
                vm.serviceLimitationsByCodeSet.sort(function (a, b) {
                    return parseFloat(a.AGE_MIN) - parseFloat(b.AGE_MIN);
                });
                vm.serviceLimitationsByAge = vm.serviceLimitationsByCodeSet.reduce((acc, cur) => [
                    ...acc.filter((obj) => obj.FREQUENCY != cur.FREQUENCY || obj.DESCRIPTION_SHORT != cur.DESCRIPTION_SHORT), cur
                ], []);
                deferred.resolve(true);
            });
            return deferred.promise;

        }

        vm.getBenefitSummaryWaitingPeriods = function () {
            vm.loadingWaitingPeriods = false;
            vm.waitingPeriodCodesets = [];
            vm.waitingPeriodsCodesByCodeSet = [];
            vm.benefitSummaryWaitingPeriods = [];

            var deferred = $q.defer();
            let productId = parseInt(DataService.ProductId);
            productId = isNaN(productId) ? 0 : productId;

            vm.loadingWaitingPeriods = true;
            $http({
                method: 'GET',
                url: '/BenefitSummaryReport/GetBenefitSummaryWaitingPeriods',
                params: {
                    productId: productId,
                    enrolleeId: parseInt(vm.benefitSummaryEnrolleeId),
                }
            }).then(function (data) {
                vm.benefitSummaryWaitingPeriods = data.data;
                vm.hasWaitingPeriods = vm.benefitSummaryWaitingPeriods.length > 0;
                angular.copy(vm.benefitSummaryWaitingPeriods, vm.waitingPeriodCodesets);
                angular.copy(vm.benefitSummaryWaitingPeriods, vm.waitingPeriodsCodesByCodeSet);
                vm.waitingPeriodCodesets = vm.waitingPeriodCodesets.reduce((acc, cur) => [
                    ...acc.filter((obj) => obj.CODESET_ID !== cur.CODESET_ID), cur
                ], []);

                deferred.resolve(true);
            });
            vm.loadingWaitingPeriods = false;
            return deferred.promise;
        }

        vm.getBenefitSummaryCopayAmounts = function (productPeriod, productId) {
            vm.benefitSummaryCopays = [];
            vm.benefitSummaryCopaysOOA = [];
            vm.hasCopays = false;
            vm.hasCopaysOON = false;
            var deferred = $q.defer();
            
            $http({
                method: 'GET',
                url: '/BenefitSummaryReport/GetBenefitSummaryReportCopayData',
                params: {
                    productId: productId,
                    productPeriod: productPeriod
                }
            }).then(function (data) {
                vm.benefitSummaryCopays = data.data;
                if (vm.benefitSummaryCopays.length > 0) {
                    angular.copy(vm.benefitSummaryCopays, vm.benefitSummaryCopaysOOA);
                    vm.benefitSummaryCopaysOOA = vm.benefitSummaryCopaysOOA.filter(function (item) { return item.OON_FLAG == 1 });
                    vm.benefitSummaryCopays = vm.benefitSummaryCopays.filter(function (item) { return item.OON_FLAG == 0 });
                    vm.hasCopays = vm.benefitSummaryCopays.length > 0;
                    vm.hasCopaysOON = vm.benefitSummaryCopaysOOA.length > 0;
                }
                deferred.resolve(true);
            });

            vm.loadingCoinsurance = false;
            return deferred.promise;
        }

        vm.resetBenefitSummaryModal = function () {
            document.getElementById('#BenefitSummaryReportTabsgeneralInfoTabTab').className = "active active";
            document.getElementById('BenefitSummaryReportTabsgeneralInfoTabPanel').className = "active tab-pane";

            document.getElementById('#BenefitSummaryReportTabsserviceLimitationsTabTab').className = "";

            if (document.getElementById('BenefitSummaryReportTabsserviceLimitationsTabPanel') != null) {
                document.getElementById('BenefitSummaryReportTabsserviceLimitationsTabPanel').className = "tab-pane";
            }

            document.getElementById('#BenefitSummaryReportTabscoveredServicesTabTab').className = "";
            if (document.getElementById('BenefitSummaryReportTabscoveredServicesTabPanel') != null) {
                document.getElementById('BenefitSummaryReportTabscoveredServicesTabPanel').className = "tab-pane";
            }
        }

      
        $("#procedureCodeSearch").keydown(function (event) {
            if (event.which == 13) {
                vm.procedureCodeSearch(vm.searchCode);
            }
        });

        vm.printDownloadSummary = function () {
            var printOutput = "";
            vm.loadingForPrint = false;

            var style = "<style>.generalInfoResultsTable td {"
            style += "line-height: 25px;"
            style += "padding: 10px;"
            style += "border-style: solid;"
            style += "border-width: thin;"
            style += "border-color: #9d9696;"
            style += "}"
            style += ".generalInfoResults{"
            style += "height:35px;"
            style += "}"
            style += ".itemAmount{"
            style += "color:#334CA0FD"
            style += "}"
            style += " html, body {"
            style += "max-width: 100%;"
            style += "} ";
            style += "@media print {";
            style += "body {";
            style += "margin-top: 5px";
            style += "margin-left: 0px";
            style += "transform: scale(0.0)";
            style += "}</style>  <br> ";

            let promise = vm.getCoveredServices();
            vm.loadingForPrint = true;
            promise.then(function () {
                let promise2 = vm.getBenefitSummaryWaitingPeriods();
                promise2.then(function () {
                    let promise3 = vm.getServiceLimitationsData();

                    promise3.then(function () {

                        $timeout(function () {
                            let benefitSummaryReportPrintContents = "";
                            let mmemberInfo = document.getElementById('BenefitSummaryPanelHeading').innerHTML;
                            let memberHeaderData = document.getElementById('memberHeaderInformation').innerHTML;
                            let generalInfoData = document.getElementById('generalInformationResultsInNetwork').innerHTML;
                            let generalInfoDataOON = document.getElementById('generalInformationResultsOutOfNetwork').innerHTML;
                            let serviceLimitationsData = document.getElementById('serviceLimitationsResults').innerHTML;
                            let serviceLimitationsCodesetsData = document.getElementById('serviceLimitationsCodesetsResults').innerHTML;
                            let waitingPeriodData = document.getElementById('waitingPeriodResults').innerHTML;
                            let coveredServicesData = document.getElementById('coveredServicesResults').innerHTML;

                            benefitSummaryReportPrintContents = style;
                            benefitSummaryReportPrintContents += mmemberInfo;
                            benefitSummaryReportPrintContents += memberHeaderData;
                            benefitSummaryReportPrintContents += generalInfoData;
                            benefitSummaryReportPrintContents += generalInfoDataOON;
                            benefitSummaryReportPrintContents += serviceLimitationsData;
                            benefitSummaryReportPrintContents += serviceLimitationsCodesetsData;
                            benefitSummaryReportPrintContents += waitingPeriodData;
                            benefitSummaryReportPrintContents += coveredServicesData;

                            printOutput = $sce.trustAsHtml(benefitSummaryReportPrintContents);

                            let printWindow = window.open('', '', 'width=900, height=500');
                            printWindow.document.write(printOutput);
                            printWindow.print();
                            printWindow.document.close();
                            printWindow.focus();
                            vm.loadingForPrint = false;
                        }, 3000);
                    });
                });
            });
        }



    }


})();;
(function () {
    'use strict'
    angular
        .module('MWPApp')
        .component('noAccessCustomBenefitSummaryReport', {
            templateUrl: '/MWP/EnrollmentSummary/NoAccessCustomBenefitSummaryReport',
            controller: NoAccessCustomBenefitSummaryReportController,
            controllerAs: 'vm',
            bindings: {
                modalInstance: '<'
            }
        });

    NoAccessCustomBenefitSummaryReportController.$inject = ['DataService', 'WbxModalService'];

    function NoAccessCustomBenefitSummaryReportController(dataService, wbxModalService) {

        var vm = this;
        vm.$onInit = init;
        vm.cancel = cancel;

        function init() {
            console.log("NoAccessCustomBenefitSummaryReportController");
            vm.voicePhone = dataService.PortalInfo.VoicePhone;
            vm.customerServiceEmail = dataService.PortalInfo.CustomerServiceEmail;
        }

        function cancel() {
            vm.modalInstance.close('cancel');
        }
    }
})();;
(function () {
    'use strict'

    angular
        .module('MWPApp')
        .component('updateEscalationTierModalComponent', {
            templateUrl: '/MWP/EnrollmentSummary/UpdateEscalationTierModal',
            controller: UpdateEscalationTierModalController,
            controllerAs: 'vm',
            bindings: {
                modalInstance: '<',
                resolve: '<'
            }
        });

    UpdateEscalationTierModalController.$inject = ['$translate', 'wbxListErrorsService', 'UpdateEscalationTierModalService', 'ImpersonateService'];

    function UpdateEscalationTierModalController($translate, wbxListErrorsService, updateEscalationTierModalService, impersonateService) {
        var vm = this;
        vm.$onInit = init;
        vm.cancel = cancel;
        vm.submit = submit;

        function init() {
            impersonateService.getImpersonateSessionInfo()
                .then(function (response) {
                    vm.isImpersonation = response.IsImpersonation;
                });

            const planName = vm.resolve.params.planName;
            vm.documents = [];
            vm.uploadDocumentsParams = {
                enrolleeId: vm.resolve.params.insuredEnrolleeId,
                metadata: {
                    "Graduated_Benefit_Request":"true"
                }
            }
            vm.insuredEnrolleeId = vm.resolve.params.insuredEnrolleeId;
            vm.modalBodyText = $translate.instant('EnrollmentSummary_EscalationTier_Update_ModalText', { planName: planName });
        }
        function cancel() {
            vm.modalInstance.close(getResponse('cancel'));
        }
        function submit() {
            vm.updateEscalationTierModalForm.$setSubmitted();
            vm.updateEscalationTierModalForm['documents'].$setValidity('required', vm.documents.length > 0);
            if (vm.updateEscalationTierModalForm.$invalid) {
                vm.errors = wbxListErrorsService.getErrorListForBanner(vm.updateEscalationTierModalForm);
                return;
            }

            const payload = {
                documentIds : vm.documents.map(x => x.documentId)
            }
            updateEscalationTierModalService.updateEsclationTierDocuments(payload)
                .then(()=>vm.modalInstance.close(getResponse('success')))

        }
        function getResponse(result, data) {
            return { result: result, data: data };
        }
    }
})();;
(function () {
    "use strict";
    angular
        .module("MWPApp")
        .component("addNewPlan", {
            templateUrl: "addNewPlanTemplate",
            controller: AddNewPlanController,
            controllerAs: "vm",
            bindings: {

            }
        });
    AddNewPlanController.$inject = ["DataService", "$scope", "$translate", "$stateParams", "ImpersonateService", "PlanManagementApiService", "PlanManagementService", "PaymentMethodService", "wbxListErrorsService", "WbxModalService", "$window", "$q", "$state"];
    function AddNewPlanController(dataService, $scope, $translate, $stateParams, impersonateService, planManagementApiService, planManagementService, paymentMethodService, wbxListErrorsService, wbxModalService, $window, $q, $state) {
        let vm = this;
        const TARGET_WINDOW_SELF = "_self";
        const BILLING_CYCLE_TYPE_MONTHLY = '1';
        const BILLING_CYCLE_TYPE_ANNUALLY = '4';
        const UNIX_EPOCH_YEAR = 1970;
        const RELATIONSHIP_SELF = "18";
        const RELATIONSHIP_CHILD = "19";
        const RELATIONSHIP_SPOUSE = "01";
        const RELATIONSHIP_LIFE_PARTNER = "53";
        const PLAN_TYPE_STEP = 1;
        const ENROLL_DEPENDENTS_STEP = 2;
        const BILLING_INFORMATION_STEP = 3;

        vm.billingCycleType = String($stateParams.billingCycleType);
        vm.billingCycleTypeMonthly = BILLING_CYCLE_TYPE_MONTHLY;
        vm.billingCycleTypeAnnually = BILLING_CYCLE_TYPE_ANNUALLY;
        vm.effectiveDate = $stateParams.effectiveDate;
        vm.premiumGroup = $stateParams.premiumGroup;
        vm.originalPlans = $stateParams.subscriberPlans;
        vm.insuredEnrollee = $stateParams.insuredEnrollee;
        vm.sortedPremiumTypesForAllPlans = [];
        vm.isPremiumTypeListEmpty = false;
        vm.showPlanTypeGrid = true;
        vm.showDependentGrid = false;
        vm.showBillingGrid = false;
        vm.isNewDependent = false;
        vm.existingDependentsDropdown = [];
        vm.enrolledDependentList = [];
        vm.newDependentsAdded = [];
        vm.relaionshipListPristine = [];
        vm.relationshipList = [];
        vm.$onInit = $onInit;
        vm.getPremiumTypesBySelectedProductId = getPremiumTypesBySelectedProductId;
        vm.addNewDependent = addNewDependent;
        vm.addToEnrolledDependentList = addToEnrolledDependentList;
        vm.removeDependentFromEnrolledList = removeDependentFromEnrolledList;
        vm.validateToNextStep = validateToNextStep;
        vm.saveNewDependent = saveNewDependent;
        vm.getMembersOnPlanCommaSeparated = getMembersOnPlanCommaSeparated;
        vm.getBillingSummary = getBillingSummary;
        vm.back = back;
        vm.openUpdatePaymentMethodModal = openUpdatePaymentMethodModal;
        vm.customErrorMessageList = [];
        vm.editStep = editStep;
        vm.planTypeStep = PLAN_TYPE_STEP;
        vm.enrollDependentsStep = ENROLL_DEPENDENTS_STEP;
        vm.billingInformationStep = BILLING_INFORMATION_STEP;
        vm.currentStep = PLAN_TYPE_STEP;
        vm.submitNewPlan = submitNewPlan;
        vm.voicePhone = dataService.PortalInfo.VoicePhone;
        vm.customerServiceEmail = dataService.PortalInfo.CustomerServiceEmail;
        vm.getDuplicateDependentTranslationParams = getDuplicateDependentTranslationParams;
        vm.getCantAddPlanCombinationTranslationParams = getCantAddPlanCombinationTranslationParams;
        vm.getDependentAgeCutoffParams = getDependentAgeCutoffParams;
        vm.customErrors = {
            DateOfBirthTextBox: {
                isOlderThanDependentAgeCutoff: `PlanManagement_AddNewPlan_Validation_DependentMustBeYoungerThanAgeCutoff ((dependentAgeCutoff: ${dataService.DependentAgeCutoff}))`
            }
        };
        vm.checkedDependentAddress = true;
        vm.paymentMethodsType = {
            creditCard: 'CreditCard',
            ach: 'ACH'
        };
        vm.onChangeRelationship = onChangeRelationship;
        vm.isInitialCallToGetDependentsNotOnCurrentPlan = true;
        vm.isSubmitDisabled = false;

        function $onInit() {
            setPageTitle($translate.instant("PlanManagement_AddNewPlan_Title"));
            console.log(planManagementApiService)
            getPlans();
            getGender();
            getRelationship();
            getStates();
            getPaymentMethod();
            getSubscriberDetail();
            loadDataForStripe();
            impersonateService.getImpersonateSessionInfo()
                .then(function (response) {
                    vm.isImpersonation = response.IsImpersonation;
                });
        }

        function setPageTitle(title) {
            document.title = title;
        }

        function getSubscriberDetail() {
            planManagementApiService.getSubscriberDetails()
                .then(function (response) {
                    vm.subscriberDetailForPrint = response.data;
                });
        }

        function getPlans() {
            planManagementApiService.getPlans($stateParams.planTypes, vm.premiumGroup, vm.effectiveDate)
                .then(function (response) {
                    vm.plans = response.data;

                    const allPlanPremiumTypes = response.data.map(x =>
                        x.plansWithDetails.map(plan =>
                            plan.premiumTypes.map(premiumTypesForPlan =>
                                premiumTypesForPlan
                            )
                        )
                    );
                    const plansWithSortedRateDetails = getSortedPremiumTypesForAllPlans(allPlanPremiumTypes);

                    vm.sortedPremiumTypesForAllPlans = plansWithSortedRateDetails.flatMap(planWithRateDetails => {
                        return planWithRateDetails.map(rateDetail => {
                            return rateDetail.map(x => {
                                x.typeDescriptionWithRate = `${x.typeDescription} $${x.rate}`
                                return x;
                            });
                        })
                    })
                });
        }

        function getSortedPremiumTypesForAllPlans(allPlanPremiumTypes) {

            const sortedPremiumTypesForAllPlans = allPlanPremiumTypes.map(premiumTypesForPlan => {
                return sortPremiumTypesByAmountAscending(premiumTypesForPlan);
            });

            return sortedPremiumTypesForAllPlans;
        }

        function getPremiumTypesBySelectedProductId(productId) {
            if (!productId) return;
            vm.premiumTypeList = vm.sortedPremiumTypesForAllPlans.find(premiumTypesForPlan => premiumTypesForPlan[0].productId == productId);
        }

        function sortPremiumTypesByAmountAscending(premiumTypeList) {
            if (premiumTypeList === null) return;

            return premiumTypeList.map(premiumTypes => {
                return premiumTypes.sort((a, b) => Number(a.rate) - Number(b.rate));
            });
        }

        function setGridItemAsHide() {
            if (vm.showPlanTypeGrid) {
                vm.showPlanTypeGrid = false;
                vm.showDependentGrid = true;
            } else if (vm.showDependentGrid) {
                vm.showDependentGrid = false;
                vm.showBillingGrid = true;
                getBillingSummary();
            }
        }

        function getEnrolleeDependents() {
            let payload = {
                premiumGroupId: vm.premiumGroup,
                productId: vm.selectedProduct.productId
            };
            planManagementApiService.getEnrolleeDependents(payload).then(response => {

                vm.existingDependentsDropdown = response;

            });
        }

        function getGender() {
            vm.genderList = planManagementApiService.GENDER_DROPDOWN_OPTIONS;
        }

        function getRelationship() {
            planManagementApiService.getRelationshipList()
                .then(function (response) {
                    const filteredRelationshipList = response.data.filter(relationship => relationship.value == RELATIONSHIP_CHILD || relationship.value == RELATIONSHIP_SPOUSE || relationship.value == RELATIONSHIP_LIFE_PARTNER)

                    vm.relationshipListPristine = filteredRelationshipList;
                    vm.relationshipList = filteredRelationshipList;
                });
        }

        function getStates() {
            planManagementApiService.getStateList()
                .then(function (response) {
                    vm.stateslist = response;
                });
        }

        function addNewDependent() {
            vm.displayDuplicateDependentError = false;
            vm.displayDependentCombinationError = false;
            vm.addNewPlanForm.$setPristine()
            vm.selectedDependent = null;

            if (vm.showDependentGrid) {
                vm.showDependentGrid = false;
                vm.showAddNewDependentGrid = true;
                vm.isNewDependent = true;
                vm.checkedPlan = true;
            }
            else if (!vm.showDependentGrid) {
                vm.checkedPlan = false;
                vm.errors = undefined;
                vm.showAddNewDependentGrid = false;
                vm.showDependentGrid = true;
                vm.isNewDependent = false;
            }
            vm.checkedDependentAddress = true;

        }

        function addToEnrolledDependentList(dependent) {
            vm.displayDependentAgeCutoffError = false;
            vm.displayOnlyOneSpouseAllowedError = false;
            if (!dependent) {
                return;
            }
            if ((dependent.relationshipCode == RELATIONSHIP_LIFE_PARTNER || dependent.relationshipCode == RELATIONSHIP_SPOUSE) && isSpouseOrLifePartnerAlreadyEnrolled(vm.enrolledDependentList)) {
                vm.displayOnlyOneSpouseAllowedError = planManagementService.displayOnlyOneSpouseAllowedError();
                return;
            }
            if (dependent.relationshipCode === RELATIONSHIP_CHILD && isOlderThanDependentAgeCutoff(dependent.dob)) {
                vm.displayDependentAgeCutoffError = planManagementService.displayDependentAgeCutoffError();
                return;
            }

            const updatedLists = planManagementApiService.processEnrollDependentFromStep2(dependent, vm.existingDependentsDropdown, vm.enrolledDependentList, vm.newDependentsAdded);

            vm.existingDependentsDropdown = updatedLists.dependentsInDropdown;
            vm.enrolledDependentList = updatedLists.currentlyEnrolledDependentsInGrid;
            vm.newDependentsAdded = updatedLists.netNewDependents;

            adjustRelationshipListOnEnrollmentChange(vm.enrolledDependentList);
            updatePremiumTypeOnEnrollmentChange();
        }

        function removeDependentFromEnrolledList(dependent) {
            const updatedLists = planManagementApiService.removeDependentFromEnrollmentList(dependent, vm.existingDependentsDropdown, vm.enrolledDependentList, vm.newDependentsAdded);

            vm.existingDependentsDropdown = updatedLists.dependentsInDropdown;
            vm.enrolledDependentList = updatedLists.currentlyEnrolledDependentsInGrid;
            vm.newDependentsAdded = updatedLists.netNewDependents;

            adjustRelationshipListOnEnrollmentChange(vm.enrolledDependentList);
            updatePremiumTypeOnEnrollmentChange();
        }

        function validateToNextStep() {
            if (vm.currentStep == 2) {
                const payload = {
                    premiumGroupId: vm.premiumGroup,
                    productId: vm.selectedProduct.productId,
                    spouseFlag: planManagementApiService.isSpouseCurrentlyEnrolled(vm.enrolledDependentList),
                    childCount: planManagementApiService.getChildCount(vm.enrolledDependentList),
                    effectiveDate: vm.effectiveDate
                };

                planManagementApiService.doesDependentCombinationMapToPremiumType(payload).then(response => {
                    if (!response.data) {
                        vm.displayDependentCombinationError = planManagementService.displayDependentCombinationError();
                        return;
                    }
                    validateFormValues();
                })
            }
            else {
                validateFormValues();
            }
        }

        function validateFormValues() {
            if ($scope.vm.addNewPlanForm.$invalid) {
                vm.errors = wbxListErrorsService.getErrorListForBanner($scope.vm.addNewPlanForm);
                if (vm.errors.length == 0) {
                    setInitialValuesForStep2();
                    updatePremiumTypeOnEnrollmentChange();
                    setGridItemAsHide();
                } else {
                    $scope.vm.addNewPlanForm.$setSubmitted();
                    return;
                }
            } else {
                setInitialValuesForStep2();
                updatePremiumTypeOnEnrollmentChange();
                setGridItemAsHide();
            }

            vm.currentStep++;
        }

        function editStep(step) {
            vm.displayDuplicateDependentError = false;
            vm.displayDependentCombinationError = false;
            vm.displayDependentAgeCutoffError = false;
            vm.displayOnlyOneSpouseAllowedError = false;
            clearNewDependentsInputs();
            vm.addNewPlanForm.AddNewPlanDependentDOBTextBox.$setValidity("isOlderThanDependentAgeCutoff", true);

            if (step === PLAN_TYPE_STEP) {
                showPlanTypeStep();
            } else {
                showEnrollDependentsStep();
            }
            vm.currentStep = step;
        }

        function showPlanTypeStep() {
            vm.checkedPlan = false;
            vm.errors = undefined;
            vm.showAddNewDependentGrid = false;
            vm.isNewDependent = false;
            vm.showPlanTypeGrid = true;
            vm.showDependentGrid = false;
            vm.showBillingGrid = false;
        }

        function showEnrollDependentsStep() {
            vm.showPlanTypeGrid = false;
            vm.showDependentGrid = true;
            vm.showBillingGrid = false;
        }

        function saveNewDependent() {
            if (vm.addNewPlanForm.$invalid) {
                if (vm.selectedRelationship != undefined) {
                    if (vm.selectedRelationship.value === RELATIONSHIP_CHILD) {
                        vm.addNewPlanForm.AddNewPlanDependentDOBTextBox.$setValidity("isOlderThanDependentAgeCutoff", !isOlderThanDependentAgeCutoff(vm.dobInput));
                    }
                }
                vm.step2ValidationErrors = wbxListErrorsService.getErrorListForBanner(vm.addNewPlanForm);

                if (vm.step2ValidationErrors.length > 0) {
                    $scope.vm.addNewPlanForm.$setSubmitted();
                    return;
                }
            }

            const newDependentBase = {
                firstName: vm.firstNameInput.toUpperCase(),
                middleName: vm.middleNameInput ? vm.middleNameInput.toUpperCase() : undefined,
                lastName: vm.lastNameInput.toUpperCase(),
                suffix: vm.suffixInput,
                dob: vm.dobInput,
                gender: vm.selectedGender,
                relationshipCode: vm.selectedRelationship.value,
                relationshipDescription: vm.selectedRelationship.text,
                enrolleId: undefined,
                sameSubscriberAddress: vm.checkedDependentAddress
            }

            planManagementApiService.isDuplicateDependent(newDependentBase).then(response => {
                const isDuplicateDependent = response.data;
                const isDuplicateNetNewDependent = planManagementApiService.isNewDependentAlreadyInEnrolledList(vm.enrolledDependentList, newDependentBase);

                if (!isDuplicateDependent && !isDuplicateNetNewDependent) {
                    continueSaveNewDependent(newDependentBase);
                }

                else if (isDuplicateDependent || isDuplicateNetNewDependent) {
                    vm.displayDuplicateDependentError = planManagementService.displayDuplicateDepenentError();
                }
            });
        }

        function onChangeRelationship() {
            if (!!vm.selectedRelationship && vm.selectedRelationship.value !== RELATIONSHIP_CHILD) {
                vm.addNewPlanForm.AddNewPlanDependentDOBTextBox.$setValidity("isOlderThanDependentAgeCutoff", true);
                vm.addNewPlanForm.$setPristine();
            }
        }

        function continueSaveNewDependent(newDependentBase) {

            const dependentAddress = vm.checkedDependentAddress
                ? {}
                : {
                    addressOne: vm.address1Input,
                    addressTwo: vm.address2Input,
                    city: vm.cityInput,
                    state: vm.selectedDependantAddressState,
                    zip: vm.zipInput,
                    phone: vm.phoneInput
                };

            const netNewDependent = {
                ...newDependentBase,
                dependentAddress
            };

            const updatedLists = planManagementApiService.processEnrollDependentFromStep2(netNewDependent, vm.existingDependentsDropdown, vm.enrolledDependentList, vm.newDependentsAdded);

            vm.enrolledDependentList = updatedLists.currentlyEnrolledDependentsInGrid;
            vm.newDependentsAdded = updatedLists.netNewDependents;

            adjustRelationshipListOnEnrollmentChange(updatedLists.currentlyEnrolledDependentsInGrid);
            updatePremiumTypeOnEnrollmentChange();
            vm.addNewDependent();
            clearNewDependentsInputs();
        }

        function clearNewDependentsInputs() {
            vm.displayDuplicateDependentError = false;
            vm.displayDependentCombinationError = false;
            vm.displayDependentAgeCutoffError = false;
            vm.displayOnlyOneSpouseAllowedError = false;
            vm.firstNameInput = null;
            vm.middleNameInput = null;
            vm.lastNameInput = null;
            vm.suffixInput = null;
            vm.dobInput = null;
            vm.selectedGender = null;
            vm.selectedRelationship = null;
            if (!vm.checkedDependentAddress) {
                vm.checkedDependentAddress = true;
            }
            vm.address1Input = null;
            vm.address2Input = null;
            vm.cityInput = null;
            vm.selectedDependantAddressState = null;
            vm.zipInput = null;
            vm.phoneInput = null;
        }

        function isOlderThanDependentAgeCutoff(dateOfBirth) {
            let dobDiff = Date.now() - new Date(dateOfBirth);
            let dobDiffDate = new Date(dobDiff);
            let currentAge = Math.abs(dobDiffDate.getUTCFullYear() - UNIX_EPOCH_YEAR);
            return currentAge > +dataService.DependentAgeCutoff;
        }

        function getMembersOnPlanCommaSeparated(members) {
            let membersResult = members.map(function (member) {
                return [`${member.firstName} ${member.lastName}`];
            }).join(", ");
            return membersResult || "";
        }

        function getTotalsGivenPlans(plans) {
            if (!plans) {
                return null;
            }

            const initialValue = {
                subTotal: 0,
                billingFrequencyDiscounts: 0,
                paymentMethodDiscounts: 0,
                totalAfterDiscounts: 0
            };

            const result = plans.reduce((accum, curr) => {
                accum.subTotal += curr.subTotal;
                accum.billingFrequencyDiscounts += curr.billingFrequencyDiscount;
                accum.paymentMethodDiscounts += curr.paymentMethodDiscount;
                accum.totalAfterDiscounts += curr.totalAfterDiscounts;

                return accum;
            }, initialValue);

            const totals = {
                total: result.subTotal,
                billingFrequencyDiscount: result.billingFrequencyDiscounts,
                paymentMethodDiscount: result.paymentMethodDiscounts,
                totalAfterDiscounts: result.totalAfterDiscounts
            };

            return totals;
        }

        function getPaymentMethod() {
            vm.isLoadingPaymentMethod = true;
            paymentMethodService.getPaymentMethod()
                .then(function (response) {
                    vm.isLoadingPaymentMethod = false;
                    vm.paymentMethod = response.data;
                });
        }

        function loadDataForStripe() {
            paymentMethodService
                .getAllEnrolleePaymentMethods()
                .then(function (response) {
                    vm.enrolleePaymentMethods =
                        response && response.data && response.data.length
                            ? response.data
                            : [];

                    if (dataService.PaymentGateway.paymentGatewayType !== "Stripe" &&                 
                        dataService.PaymentGateway.paymentGatewayType !== "StripeAchNoVerify") {
                        return;
                    }

                    vm.paymentGatewayCustomerId =
                        vm.enrolleePaymentMethods.find((epm) =>
                            epm.paymentGatewayCustomerId.startsWith("cus_")
                        ).paymentGatewayCustomerId || "";

                    if (vm.paymentGatewayCustomerId) {
                        return paymentMethodService.createSetupIntent(
                            dataService.PaymentGateway.paymentGatewayId,
                            vm.paymentGatewayCustomerId
                        );
                    } else {
                        return paymentMethodService.createCustomerAndSetupIntent(
                            dataService.PaymentGateway.paymentGatewayId,
                            dataService.FullName,
                            dataService.Email
                        );
                    }
                })
                .then(function (response) {
                    if (!response) {
                        return;
                    }

                    if (!response.PaymentGatewayPreAuthToken) {
                        return;
                    }

                    if (response.PaymentGatewayCustomerId) {
                        vm.paymentGatewayCustomerId = response.PaymentGatewayCustomerId;
                    }

                    vm.clientSecret = response.PaymentGatewayPreAuthToken;
                    vm.Stripe = Stripe(dataService.PaymentGateway.publicKey);
                    vm.elements = vm.Stripe.elements({
                        clientSecret: vm.clientSecret,
                        appearance: {
                            variables: {
                                fontWeightNormal: "400",
                                fontFamily: '"ui-sans-serif", system-ui, -apple-system',
                                fontSizeBase: "14px",
                                colorTextPlaceholder: "#CFD7E0",
                            },
                            theme: "stripe",
                        },
                        loader: "always",
                    });
            });
        }
        
        function back() {
            $state.go('planManagement');
        }

        function handleUpdatePaymentMethodModalClosed() {
            if (dataService.PaymentGateway.paymentGatewayType === "Stripe" ||                 
                dataService.PaymentGateway.paymentGatewayType === "StripeAchNoVerify") {
                return paymentMethodService
                    .createSetupIntent(
                        dataService.PaymentGateway.paymentGatewayId,
                        vm.paymentGatewayCustomerId
                    )
                    .then((response) => {
                        vm.clientSecret = response.PaymentGatewayPreAuthToken;
                        vm.elements = vm.Stripe.elements({
                            clientSecret: vm.clientSecret,
                            appearance: {
                                variables: {
                                    fontWeightNormal: "400",
                                    fontFamily: '"ui-sans-serif", system-ui, -apple-system',
                                    fontSizeBase: "14px",
                                    colorTextPlaceholder: "#CFD7E0",
                                },
                                theme: "stripe",
                            },
                            loader: "always",
                        });
                    });
            }
            getBillingSummary();
        }

        function openUpdatePaymentMethodModal() {
            let modalDefaults = {
                backdrop: "static",
                keyboard: true,
                modalFade: true,
                component: "updatePaymentMethodModal",
                size: "lg",
                windowClass: "",
                resolve: {
                    Stripe: function () {
                        return vm.Stripe;
                    },
                    elements: function () {
                        return vm.elements;
                    },
                    paymentGatewayCustomerId: function () {
                        return vm.paymentGatewayCustomerId;
                    },
                },
            };
            wbxModalService.showModal(modalDefaults, {})
                .then(() => {
                    getPaymentMethod();
                    
                    handleUpdatePaymentMethodModalClosed();
                });
        }

        function submitNewPlan() {
            vm.isSubmitDisabled = true;
            const existingDependentsToEnroll = vm.enrolledDependentList.filter(x => x.enrolleeId);
            const netNewDependentsToEnroll = vm.newDependentsAdded;
            let allDependentsToEnroll = [];

            if (existingDependentsToEnroll.length > 0 && netNewDependentsToEnroll.length > 0) {
                allDependentsToEnroll = [...existingDependentsToEnroll, ...netNewDependentsToEnroll];
            }
            else if (netNewDependentsToEnroll.length > 0) {
                allDependentsToEnroll = netNewDependentsToEnroll;
            }
            else {
                allDependentsToEnroll = existingDependentsToEnroll;
            }

            let submitedNewPlanDTO = {
                subscriberId: dataService.SubscriberId,
                enrolleeId: dataService.EnrolleeId,
                dependentForNewPlan: allDependentsToEnroll,
                newPlan: { effectiveDate: vm.effectiveDate, newPlanProduct: vm.selectedProduct, premiumGroupId: vm.premiumGroup },
                paymentFrequency: +vm.billingCycleType
            }
            planManagementApiService.submitNewPlan(JSON.parse(angular.toJson(submitedNewPlanDTO))).then(function (response) {
                if (response.data.IsSuccess == true) {
                    $state.go('planManagement');
                } else {
                    const errors = { messageTranslationKey: response.data.Message };
                    vm.customErrorMessageList.push(errors);
                    vm.isSubmitDisabled = false;
                }
            });
        }

        function getBillingSummary() {
            const selectedPlan = {
                ProductId: vm.selectedProduct.productId,
                EmbeddedLifeProductId: vm.selectedProduct.embeddedLifeProductId,
                PremiumGroupId: vm.premiumGroup,
                ProductDescription: vm.selectedProduct.name,
                LineOfBusinessDescription: vm.selectedProduct.lineOfBusinessDescription,
                MemberList: getMemberListForBillingSummary()
            }
            const plans = planManagementService.getPlansForBillingSummary(vm.originalPlans, selectedPlan);

            planManagementApiService.getBillingSummary(plans, +vm.billingCycleType)
                .then(function (response) {
                    const planItemDetails = response.data;

                    const billingSummaryForPlans = planItemDetails.map(planItemDetail => {
                        return {
                            productId: planItemDetail.productId,
                            premiumGroupId: planItemDetail.premiumGroupId,
                            planName: planItemDetail.planName,
                            planType: planItemDetail.planType,
                            members: planItemDetail.members,
                            coverageLevel: planItemDetail.coverageLevel,
                            rate: planItemDetail.rate,
                            frequencyTotal: planItemDetail.frequencyTotal,
                            subTotal: planItemDetail.subTotal,
                            billingFrequencyDiscount: planItemDetail.billingFrequencyDiscount,
                            paymentMethodDiscount: planItemDetail.paymentMethodDiscount,
                            totalAfterDiscounts: planItemDetail.totalAfterDiscounts
                        };
                    });

                    vm.billingSummaryPlans = billingSummaryForPlans;

                    updateTotalsOnChange();
                });
        }

        function updateTotalsOnChange() {
            let totals = getTotalsGivenPlans(vm.billingSummaryPlans);

            vm.totals = totals
        }

        function getDependentAgeCutoffParams() {
            return { dependentAgeCutoff: dataService.DependentAgeCutoff } 
        }

        function getDuplicateDependentTranslationParams() {
            return { phone: vm.voicePhone, email: vm.customerServiceEmail };
        }

        function getCantAddPlanCombinationTranslationParams() {
            return { plansCantAddDependent: vm.selectedProduct.name, phone: vm.voicePhone, email: vm.customerServiceEmail };
        }

        function adjustRelationshipListOnEnrollmentChange(enrolledDependentList) {
            if (isSpouseOrLifePartnerAlreadyEnrolled(enrolledDependentList)) {
                vm.relationshipList = removeSpouseOrLifePartnerFromRelationshipDropDownWhenAlreadyEnrolled(vm.relationshipListPristine);
            }
            else {
                vm.relationshipList = vm.relationshipListPristine;
            }
        }

        function isSpouseOrLifePartnerAlreadyEnrolled(enrolledDependentsList) {
            return enrolledDependentsList.some(enrollee => enrollee.relationshipCode === RELATIONSHIP_LIFE_PARTNER || enrollee.relationshipCode === RELATIONSHIP_SPOUSE);
        }

        function removeSpouseOrLifePartnerFromRelationshipDropDownWhenAlreadyEnrolled(relationshipList) {
            return relationshipList.filter(relationship => relationship.value == RELATIONSHIP_CHILD);
        }

        function setInitialValuesForStep2() {
            if (vm.isInitialCallToGetDependentsNotOnCurrentPlan) {
                vm.isInitialCallToGetDependentsNotOnCurrentPlan = false;

                getEnrolleeDependents();
            }

            adjustRelationshipListOnEnrollmentChange(vm.enrolledDependentList);
        }

        function getMemberListForBillingSummary() {
            if (vm.originalPlans) {
                const primarySubscriber = vm.insuredEnrollee;

                return [primarySubscriber, ...vm.enrolledDependentList];
            }
        }

        function updatePremiumTypeOnEnrollmentChange() {
            const payload = {
                premiumGroupId: vm.premiumGroup,
                productId: vm.selectedProduct.productId,
                spouseFlag: planManagementApiService.isSpouseCurrentlyEnrolled(vm.enrolledDependentList),
                childCount: planManagementApiService.getChildCount(vm.enrolledDependentList),
                effectiveDate: vm.effectiveDate
            };

            planManagementApiService.updatePremiumTypeOnEnrollmentChange(payload, vm.premiumTypeList).then(response => {
                if (!response) {
                    return;
                }
                vm.selectedPremiumType = response;
            });
        }
    }
})();;
(function () {
    "use strict";
    angular
        .module("MWPApp")
        .component("changePlan", {
            templateUrl: "changePlanTemplate",
            controller: changePlanController,
            controllerAs: "vm",
        });
    changePlanController.$inject = ['DataService', '$scope', "$translate", '$stateParams', 'ImpersonateService', 'PlanManagementService', 'PlanManagementApiService', 'PaymentMethodService', 'wbxListErrorsService', 'WbxModalService', "$window", "$q", "$state"];
    function changePlanController(dataService, $scope, $translate, $stateParams, impersonateService, planManagementService, planManagementApiService, paymentMethodService, wbxListErrorsService, wbxModalService, $window, $q, $state) {
        const UNIX_EPOCH_YEAR = 1970;
        let vm = this;
        const TARGET_WINDOW_SELF = "_self";
        const RELATIONSHIP_SELF = "18";
        const RELATIONSHIP_CHILD = "19";
        const RELATIONSHIP_SPOUSE = "01";
        const RELATIONSHIP_LIFE_PARTNER = "53";
        const SUBSCRIBER_MEMBER_ID = "00";
        const BILLING_CYCLE_TYPE_MONTHLY = '1';
        const BILLING_CYCLE_TYPE_ANNUALLY = '4';
        const PLAN_TYPE_STEP = 1;
        const ENROLL_DEPENDENTS_STEP = 2;
        const BILLING_INFORMATION_STEP = 3;

        vm.billingCycleType = String($stateParams.billingCycleType);
        vm.billingCycleTypeMonthly = BILLING_CYCLE_TYPE_MONTHLY;
        vm.billingCycleTypeAnnually = BILLING_CYCLE_TYPE_ANNUALLY;
        vm.effectiveDate = $stateParams.effectiveDate;
        vm.premiumGroup = $stateParams.premiumGroup;
        vm.originalPlans = $stateParams.subscriberPlans;
        vm.planTypeToChange = $stateParams.planSelected.planType;
        vm.productIdToTerminate = $stateParams.planSelected.productId;
        vm.embeddedLifeProductIdToTerminate = $stateParams.planSelected.embeddedLifeProductId;
        vm.selectedPlanType = $stateParams.planSelected.planType;
        vm.sortedPremiumTypesForAllPlans = [];
        vm.premiumTypeListEmpty = false;
        vm.showPlanTypeGrid = true;
        vm.showDependentGrid = false;
        vm.showBillingGrid = false;
        vm.dependentsAlreadyEnrolledOnSelectedPlan = $stateParams.dependents.filter(enrollee => enrollee.memberId !== SUBSCRIBER_MEMBER_ID)
        vm.existingDependentsDropdown = [];
        vm.enrolledDependentList = [...vm.dependentsAlreadyEnrolledOnSelectedPlan];
        vm.newDependentsAdded = [];
        vm.relaionshipListPristine = [];
        vm.relationshipList = [];
        vm.customErrorMessageList = [];
        vm.$onInit = $onInit;
        vm.getPremiumTypesBySelectedProductId = getPremiumTypesBySelectedProductId;
        vm.addNewDependent = addNewDependent;
        vm.addToEnrolledDependentList = addToEnrolledDependentList;
        vm.removeDependentFromEnrolledList = removeDependentFromEnrolledList;
        vm.validateToNextStep = validateToNextStep;
        vm.saveNewDependent = saveNewDependent;
        vm.getMembersOnPlanCommaSeparated = getMembersOnPlanCommaSeparated;
        vm.getBillingSummary = getBillingSummary;
        vm.back = back;
        vm.openUpdatePaymentMethodModal = openUpdatePaymentMethodModal;
        vm.submitChangePlan = submitChangePlan;
        vm.checkedDependentAddress = true;
        vm.editStep = editStep;
        vm.planTypeStep = PLAN_TYPE_STEP;
        vm.enrollDependentsStep = ENROLL_DEPENDENTS_STEP;
        vm.billingInformationStep = BILLING_INFORMATION_STEP;
        vm.currentStep = PLAN_TYPE_STEP;
        vm.paymentMethodsType = {
            creditCard: 'CreditCard',
            ach: 'ACH'
        };
        vm.voicePhone = dataService.PortalInfo.VoicePhone;
        vm.customerServiceEmail = dataService.PortalInfo.CustomerServiceEmail;
        vm.getDuplicateDependentTranslationParams = getDuplicateDependentTranslationParams;
        vm.getCantAddPlanCombinationTranslationParams = getCantAddPlanCombinationTranslationParams;
        vm.getDependentAgeCutoffParams = getDependentAgeCutoffParams;
        vm.onChangeRelationship = onChangeRelationship;
        vm.isInitialCallToGetDependentsNotOnCurrentPlan = true;
        vm.isSubmitDisabled = false;
        vm.isImpersonation = false;

        function $onInit() {
            setPageTitle($translate.instant("PlanManagement_ChangePlan_Title"));
            getPlansToChange();
            getGender();
            getRelationship();
            getStates();
            getPaymentMethod();
            vm.customErrors = {
                DateOfBirthTextBox: {
                    isOlderThanDependentAgeCutoff: `PlanManagement_AddNewPlan_Validation_DependentMustBeYoungerThanAgeCutoff ((dependentAgeCutoff: ${dataService.DependentAgeCutoff}))`
                }
            };
            loadDataForStripe();
            impersonateService.getImpersonateSessionInfo()
                .then(function (response) {
                    vm.isImpersonation = response.IsImpersonation;
                });
        }

        function setPageTitle(title) {
            document.title = title;
        }

        function getPlansToChange() {
            planManagementApiService.getPlansToChange(vm.effectiveDate, vm.planTypeToChange, vm.premiumGroup, $stateParams.planSelected.productId)
                .then(function (response) {
                    vm.plans = response.data;
                    const allPlanPremiumTypes = response.data.plansWithDetails.map(plan => plan.premiumTypes.map(premiumTypesForPlan => premiumTypesForPlan));

                    const sortedPremiumTypes = getSortedPremiumTypesForAllPlans(allPlanPremiumTypes);
                    vm.sortedPremiumTypesForAllPlans = sortedPremiumTypes.map(rateDetail => {
                        return rateDetail.map(x => {
                            x.typeDescriptionWithRate = `${x.typeDescription} $${x.rate}`
                            return x;
                        })
                    })
                });
        }

        function getSortedPremiumTypesForAllPlans(allPlanPremiumTypes) {

            const sortedPremiumTypesForAllPlans = allPlanPremiumTypes.map(premiumTypesForPlan => {
                return sortPremiumTypesByAmountAscending(premiumTypesForPlan);
            });

            return sortedPremiumTypesForAllPlans;
        }

        function getPremiumTypesBySelectedProductId(productId) {
            if (!productId) return;

            vm.premiumTypeList = vm.sortedPremiumTypesForAllPlans.find(premiumTypesForPlan => premiumTypesForPlan[0].productId == productId);
        }

        function getlineOfBusinessId(lineOfBusinessDescription) {
            if (lineOfBusinessDescription == "Vision") {
                return 3;
            } else if (lineOfBusinessDescription == "Dental") {
                return 2;
            } else {
                //Life Insurance
                return 9;
            }
        }

        function sortPremiumTypesByAmountAscending(premiumTypeList) {
            if (premiumTypeList === null) return;

            return premiumTypeList.sort((a, b) => Number(a.rate) - Number(b.rate));
        }

        function setGridItemAsHide() {
            if (vm.showPlanTypeGrid) {
                vm.showPlanTypeGrid = false;
                vm.showDependentGrid = true;

            } else if (vm.showDependentGrid) {
                vm.showDependentGrid = false;
                vm.showBillingGrid = true;
                getBillingSummary();
            }
        }

        function getEnrolleeDependents() {
            let payload = {
                premiumGroupId: $stateParams.planSelected.premiumGroupId,
                productId: $stateParams.planSelected.productId
            };
            planManagementApiService.getEnrolleeDependents(payload, vm.dependentsAlreadyEnrolledOnSelectedPlan).then(response => {

                vm.existingDependentsDropdown = response;

            });
        }

        function getGender() {
            vm.genderList = planManagementApiService.GENDER_DROPDOWN_OPTIONS;
        }

        function getRelationship() {
            planManagementApiService.getRelationshipList()
                .then(function (response) {
                    const filteredRelationshipList = response.data.filter(relationship => relationship.value == RELATIONSHIP_CHILD || relationship.value == RELATIONSHIP_SPOUSE || relationship.value == RELATIONSHIP_LIFE_PARTNER)

                    vm.relationshipListPristine = filteredRelationshipList;
                    vm.relationshipList = filteredRelationshipList;
                });
        }

        function getStates() {
            planManagementApiService.getStateList()
                .then(function (response) {
                    vm.stateslist = response;
                });
        }

        function addNewDependent() {
            vm.displayDuplicateDependentError = false;
            vm.displayDependentCombinationError = false;
            vm.changePlanForm.$setPristine()
            vm.selectedDependent = null;

            if (vm.showDependentGrid) {
                vm.showDependentGrid = false;
                vm.showAddNewDependentGrid = true;
                vm.isNewDependent = true;
                $scope.vm.changePlanForm.$valid = true;
                $scope.vm.changePlanForm.$invalid = false;
                $scope.vm.changePlanForm.$submitted = false;
                $scope.vm.checkedPlan = true;
            }
            else if (!vm.showDependentGrid) {
                $scope.vm.changePlanForm.$valid = true;
                $scope.vm.changePlanForm.$invalid = false;
                $scope.vm.changePlanForm.$submitted = false;
                $scope.vm.checkedPlan = false;
                vm.errors = undefined;
                vm.showAddNewDependentGrid = false;
                vm.showDependentGrid = true;
                vm.isNewDependent = false;
            }
            vm.checkedDependentAddress = true;
        }

        function addToEnrolledDependentList(dependent) {
            vm.displayDependentAgeCutoffError = false;
            vm.displayOnlyOneSpouseAllowedError = false;
            if (!dependent) {
                return;
            }
            if ((dependent.relationshipCode == RELATIONSHIP_LIFE_PARTNER || dependent.relationshipCode == RELATIONSHIP_SPOUSE) && isSpouseOrLifePartnerAlreadyEnrolled(vm.enrolledDependentList)) {
                vm.displayOnlyOneSpouseAllowedError = planManagementService.displayOnlyOneSpouseAllowedError();
                return;
            }
            if (dependent.relationshipCode === RELATIONSHIP_CHILD && isOlderThanDependentAgeCutoff(dependent.dob)) {
                vm.displayDependentAgeCutoffError = planManagementService.displayDependentAgeCutoffError();
                return;
            }

            const updatedLists = planManagementApiService.processEnrollDependentFromStep2(dependent, vm.existingDependentsDropdown, vm.enrolledDependentList, vm.newDependentsAdded);

            vm.existingDependentsDropdown = updatedLists.dependentsInDropdown;
            vm.enrolledDependentList = updatedLists.currentlyEnrolledDependentsInGrid;
            vm.newDependentsAdded = updatedLists.netNewDependents;

            adjustRelationshipListOnEnrollmentChange(vm.enrolledDependentList);
            updatePremiumTypeOnEnrollmentChange();
        }

        function removeDependentFromEnrolledList(dependent) {
            const updatedLists = planManagementApiService.removeDependentFromEnrollmentList(dependent, vm.existingDependentsDropdown, vm.enrolledDependentList, vm.newDependentsAdded);

            vm.existingDependentsDropdown = updatedLists.dependentsInDropdown;
            vm.enrolledDependentList = updatedLists.currentlyEnrolledDependentsInGrid;
            vm.newDependentsAdded = updatedLists.netNewDependents;

            adjustRelationshipListOnEnrollmentChange(vm.enrolledDependentList);
            updatePremiumTypeOnEnrollmentChange();
        }
        
        function validateToNextStep() {
            if (vm.currentStep == 2) {

                const payload = {
                    premiumGroupId: vm.premiumGroup,
                    productId: vm.selectedProduct.productId,
                    spouseFlag: planManagementApiService.isSpouseCurrentlyEnrolled(vm.enrolledDependentList),
                    childCount: planManagementApiService.getChildCount(vm.enrolledDependentList),
                    effectiveDate: vm.effectiveDate
                };

                planManagementApiService.doesDependentCombinationMapToPremiumType(payload).then(response => {
                    if (!response.data) {
                        vm.displayDependentCombinationError = planManagementService.displayDependentCombinationError();
                        return;
                    }
                    validateFormValues();
                })
            }
            else {
                validateFormValues();
            }
        }

        function validateFormValues() {
            if ($scope.vm.changePlanForm.$invalid) {
                vm.errors = wbxListErrorsService.getErrorListForBanner($scope.vm.changePlanForm);
                if (vm.errors.length == 0) {
                    setInitialValuesForStep2();
                    updatePremiumTypeOnEnrollmentChange();
                    setGridItemAsHide();
                } else {
                    $scope.vm.changePlanForm.$setSubmitted();
                    return;
                }
            } else {
                setInitialValuesForStep2();
                updatePremiumTypeOnEnrollmentChange();
                setGridItemAsHide();
            }

            vm.currentStep++;
        }

        function editStep(step) {
            vm.displayDuplicateDependentError = false;
            vm.displayDependentCombinationError = false;
            vm.displayDependentAgeCutoffError = false;
            vm.displayOnlyOneSpouseAllowedError = false;
            clearNewDependentsInputs();
            vm.changePlanForm.AddNewPlanDependentDOBTextBox.$setValidity("isOlderThanDependentAgeCutoff", true);


            if (step === PLAN_TYPE_STEP) {
                showPlanTypeStep();
            } else {
                showEnrollDependentsStep();
            }
            vm.currentStep = step;
        }

        function showPlanTypeStep() {
            vm.checkedPlan = false;
            vm.errors = undefined;
            vm.showAddNewDependentGrid = false;
            vm.isNewDependent = false;
            vm.showPlanTypeGrid = true;
            vm.showDependentGrid = false;
            vm.showBillingGrid = false;
        }

        function showEnrollDependentsStep() {
            vm.showPlanTypeGrid = false;
            vm.showDependentGrid = true;
            vm.showBillingGrid = false;
        }

        function saveNewDependent() {
            if (vm.changePlanForm.$invalid) {
                if (vm.selectedRelationship != undefined) {
                    if (vm.selectedRelationship.value === RELATIONSHIP_CHILD) {
                        vm.changePlanForm.AddNewPlanDependentDOBTextBox.$setValidity("isOlderThanDependentAgeCutoff", !isOlderThanDependentAgeCutoff(vm.dobInput));
                    }
                }
                vm.step2ValidationErrors = wbxListErrorsService.getErrorListForBanner(vm.changePlanForm);

                if (vm.step2ValidationErrors.length > 0) {
                    $scope.vm.changePlanForm.$setSubmitted();
                    return;
                }
            }

            const newDependentBase = {
                firstName: vm.firstNameInput.toUpperCase(),
                middleName: vm.middleNameInput ? vm.middleNameInput.toUpperCase() : undefined,
                lastName: vm.lastNameInput.toUpperCase(),
                suffix: vm.suffixInput,
                dob: vm.dobInput,
                gender: vm.selectedGender,
                relationshipCode: vm.selectedRelationship.value,
                relationshipDescription: vm.selectedRelationship.text,
                enrolleId: undefined,
                sameSubscriberAddress: vm.checkedDependentAddress
            }

            planManagementApiService.isDuplicateDependent(newDependentBase).then(response => {
                const isDuplicateDependent = response.data;
                const isDuplicateNetNewDependent = planManagementApiService.isNewDependentAlreadyInEnrolledList(vm.enrolledDependentList, newDependentBase);

                if (!isDuplicateDependent && !isDuplicateNetNewDependent) {
                    continueSaveNewDependent(newDependentBase);
                }

                else if (isDuplicateDependent || isDuplicateNetNewDependent) {
                    vm.displayDuplicateDependentError = planManagementService.displayDuplicateDepenentError();
                }
            });
        }

        function onChangeRelationship() {
            if (!!vm.selectedRelationship && vm.selectedRelationship.value !== RELATIONSHIP_CHILD) {
                vm.changePlanForm.AddNewPlanDependentDOBTextBox.$setValidity("isOlderThanDependentAgeCutoff", true);
                vm.changePlanForm.$setPristine();
            }
        }

        function continueSaveNewDependent(newDependentBase) {

            const dependentAddress = vm.checkedDependentAddress
                ? {}
                : {
                    addressOne: vm.address1Input,
                    addressTwo: vm.address2Input,
                    city: vm.cityInput,
                    state: vm.selectedDependantAddressState,
                    zip: vm.zipInput,
                    phone: vm.phoneInput
                };

            const netNewDependent = {
                ...newDependentBase,
                dependentAddress
            };

            const updatedLists = planManagementApiService.processEnrollDependentFromStep2(netNewDependent, vm.existingDependentsDropdown, vm.enrolledDependentList, vm.newDependentsAdded);

            vm.enrolledDependentList = updatedLists.currentlyEnrolledDependentsInGrid;
            vm.newDependentsAdded = updatedLists.netNewDependents;

            adjustRelationshipListOnEnrollmentChange(updatedLists.currentlyEnrolledDependentsInGrid);
            updatePremiumTypeOnEnrollmentChange();
            vm.addNewDependent();
            clearNewDependentsInputs();
        }

        function clearNewDependentsInputs() {
            vm.displayDuplicateDependentError = false;
            vm.displayDependentCombinationError = false;
            vm.displayDependentAgeCutoffError = false;
            vm.displayOnlyOneSpouseAllowedError = false;
            vm.firstNameInput = null;
            vm.middleNameInput = null;
            vm.lastNameInput = null;
            vm.suffixInput = null;
            vm.dobInput = null;
            vm.selectedGender = null;
            vm.selectedRelationship = null;
            if (!vm.checkedDependentAddress) {
                vm.checkedDependentAddress = true;
            }
            vm.address1Input = null;
            vm.address2Input = null;
            vm.cityInput = null;
            vm.selectedDependantAddressState = null;
            vm.zipInput = null;
            vm.phoneInput = null;
        }

        function isOlderThanDependentAgeCutoff(dateOfBirth) {
            let dobDiff = Date.now() - new Date(dateOfBirth);
            let dobDiffDate = new Date(dobDiff);
            let currentAge = Math.abs(dobDiffDate.getUTCFullYear() - UNIX_EPOCH_YEAR);

            return currentAge > +dataService.DependentAgeCutoff;
        }

        function getMembersOnPlanCommaSeparated(members) {
            let membersResult = members.map(function (member) {
                return [`${member.firstName} ${member.lastName}`];
            }).join(", ");
            return membersResult || "";
        }

        function getTotalsGivenPlans(plans) {
            if (!plans) {
                return null;
            }

            const initialValue = {
                subTotal: 0,
                billingFrequencyDiscounts: 0,
                paymentMethodDiscounts: 0,
                totalAfterDiscounts: 0
            };

            const result = plans.reduce((accum, curr) => {
                accum.subTotal += curr.subTotal;
                accum.billingFrequencyDiscounts += curr.billingFrequencyDiscount;
                accum.paymentMethodDiscounts += curr.paymentMethodDiscount;
                accum.totalAfterDiscounts += curr.totalAfterDiscounts;

                return accum;
            }, initialValue);

            const totals = {
                total: result.subTotal,
                billingFrequencyDiscount: result.billingFrequencyDiscounts,
                paymentMethodDiscount: result.paymentMethodDiscounts,
                totalAfterDiscounts: result.totalAfterDiscounts
            };

            return totals;
        }

        function getPaymentMethod() {
            vm.isLoadingPaymentMethod = true;
            paymentMethodService.getPaymentMethod()
                .then(function (response) {
                    vm.isLoadingPaymentMethod = false;
                    vm.paymentMethod = response.data;
                });
        }

        function loadDataForStripe() {
            paymentMethodService
                .getAllEnrolleePaymentMethods()
                .then(function (response) {
                    vm.enrolleePaymentMethods =
                        response && response.data && response.data.length
                            ? response.data
                            : [];

                    if (dataService.PaymentGateway.paymentGatewayType !== "Stripe" &&                 
                        dataService.PaymentGateway.paymentGatewayType !== "StripeAchNoVerify") {
                        return;
                    }

                    vm.paymentGatewayCustomerId =
                        vm.enrolleePaymentMethods.find((epm) =>
                            epm.paymentGatewayCustomerId.startsWith("cus_")
                        ).paymentGatewayCustomerId || "";

                    if (vm.paymentGatewayCustomerId) {
                        return paymentMethodService.createSetupIntent(
                            dataService.PaymentGateway.paymentGatewayId,
                            vm.paymentGatewayCustomerId
                        );
                    } else {
                        return paymentMethodService.createCustomerAndSetupIntent(
                            dataService.PaymentGateway.paymentGatewayId,
                            dataService.FullName,
                            dataService.Email
                        );
                    }
                })
                .then(function (response) {
                    if (!response) {
                        return;
                    }

                    if (!response.PaymentGatewayPreAuthToken) {
                        return;
                    }

                    if (response.PaymentGatewayCustomerId) {
                        vm.paymentGatewayCustomerId = response.PaymentGatewayCustomerId;
                    }

                    vm.clientSecret = response.PaymentGatewayPreAuthToken;
                    vm.Stripe = Stripe(dataService.PaymentGateway.publicKey);
                    vm.elements = vm.Stripe.elements({
                        clientSecret: vm.clientSecret,
                        appearance: {
                            variables: {
                                fontWeightNormal: "400",
                                fontFamily: '"ui-sans-serif", system-ui, -apple-system',
                                fontSizeBase: "14px",
                                colorTextPlaceholder: "#CFD7E0",
                            },
                            theme: "stripe",
                        },
                        loader: "always",
                    });
            });
        }

        function back() {
            $state.go('planManagement');
        }

        function submitChangePlan() {
            vm.isSubmitDisabled = true;
            const existingDependentsToEnroll = vm.enrolledDependentList.filter(x => x.enrolleeId);
            const netNewDependentsToEnroll = vm.newDependentsAdded;
            let allDependentsToEnroll = [];

            if (existingDependentsToEnroll.length > 0 && netNewDependentsToEnroll.length > 0) {
                allDependentsToEnroll = [...existingDependentsToEnroll, ...netNewDependentsToEnroll];
            }
            else if (netNewDependentsToEnroll.length > 0) {
                allDependentsToEnroll = netNewDependentsToEnroll;
            }
            else {
                allDependentsToEnroll = existingDependentsToEnroll;
            }

            let submitChangePlanDTO = {
                subscriberId: dataService.SubscriberId,
                enrolleeId: dataService.EnrolleeId,
                dependentForNewPlan: allDependentsToEnroll,
                productIdToTerminate: vm.productIdToTerminate,
                embeddedLifeProductIdToTerminate: vm.embeddedLifeProductIdToTerminate,
                newPlan: { effectiveDate: vm.effectiveDate, newPlanProduct: vm.selectedProduct, premiumGroupId: vm.premiumGroup },
                paymentFrequency: +vm.billingCycleType
            }

            planManagementApiService.submitChangePlan(JSON.parse(angular.toJson(submitChangePlanDTO))).then(function (response) {
                if (response.data.IsSuccess == true) {
                    $state.go('planManagement');
                } else {
                    const errors = { messageTranslationKey: response.data.Message };
                    vm.customErrorMessageList.push(errors);
                    vm.isSubmitDisabled = false;
                }
            });
        }

        function handleUpdatePaymentMethodModalClosed() {
            if (dataService.PaymentGateway.paymentGatewayType === "Stripe" || 
                dataService.PaymentGateway.paymentGatewayType === "StripeAchNoVerify") {
                return paymentMethodService
                    .createSetupIntent(
                        dataService.PaymentGateway.paymentGatewayId,
                        vm.paymentGatewayCustomerId
                    )
                    .then((response) => {
                        vm.clientSecret = response.PaymentGatewayPreAuthToken;
                        vm.elements = vm.Stripe.elements({
                            clientSecret: vm.clientSecret,
                            appearance: {
                                variables: {
                                    fontWeightNormal: "400",
                                    fontFamily: '"ui-sans-serif", system-ui, -apple-system',
                                    fontSizeBase: "14px",
                                    colorTextPlaceholder: "#CFD7E0",
                                },
                                theme: "stripe",
                            },
                            loader: "always",
                        });
                    });
            }
            getBillingSummary();
        }

        function openUpdatePaymentMethodModal() {
            let modalDefaults = {
                backdrop: "static",
                keyboard: true,
                modalFade: true,
                component: "updatePaymentMethodModal",
                size: "lg",
                windowClass: "",
                resolve: {
                    Stripe: function () {
                      return vm.Stripe;
                    },
                    elements: function () {
                      return vm.elements;
                    },
                    paymentGatewayCustomerId: function () {
                      return vm.paymentGatewayCustomerId;
                    },
                },
            };
            
            wbxModalService.showModal(modalDefaults, {})
                .then(() => {
                    getPaymentMethod();
                    
                    handleUpdatePaymentMethodModalClosed();
                });
        }

        function getBillingSummary() {
            const selectedPlan = {
                ProductId: vm.selectedProduct.productId,
                EmbeddedLifeProductId: vm.selectedProduct.embeddedLifeProductId,
                PremiumGroupId: vm.premiumGroup,
                ProductDescription: vm.selectedProduct.name,
                LineOfBusinessDescription: vm.selectedProduct.lineOfBusinessDescription,
                MemberList: getMemberListForBillingSummary()
            }
            const plans = planManagementService.getPlansForBillingSummary(vm.originalPlans, selectedPlan, vm.productIdToTerminate);

            planManagementApiService.getBillingSummary(plans, +vm.billingCycleType)
                .then(function (response) {
                    const planItemDetails = response.data;

                    const billingSummaryForPlans = planItemDetails.map(planItemDetail => {
                        return {
                            productId: planItemDetail.productId,
                            premiumGroupId: planItemDetail.premiumGroupId,
                            planName: planItemDetail.planName,
                            planType: planItemDetail.planType,
                            members: planItemDetail.members,
                            coverageLevel: planItemDetail.coverageLevel,
                            rate: planItemDetail.rate,
                            frequencyTotal: planItemDetail.frequencyTotal,
                            subTotal: planItemDetail.subTotal,
                            billingFrequencyDiscount: planItemDetail.billingFrequencyDiscount,
                            paymentMethodDiscount: planItemDetail.paymentMethodDiscount,
                            totalAfterDiscounts: planItemDetail.totalAfterDiscounts
                        };
                    });

                    vm.billingSummaryPlans = billingSummaryForPlans;

                    updateTotalsOnChange();
                });
        }

        function updateTotalsOnChange() {   
            let totals = getTotalsGivenPlans(vm.billingSummaryPlans);

            vm.totals = totals
        }

        function getDependentAgeCutoffParams() {
            return { dependentAgeCutoff: dataService.DependentAgeCutoff }
        }

        function getDuplicateDependentTranslationParams() {
            return { phone: vm.voicePhone, email: vm.customerServiceEmail };
        }

        function getCantAddPlanCombinationTranslationParams() {
            return { plansCantAddDependent: vm.selectedProduct.name, phone: vm.voicePhone, email: vm.customerServiceEmail };
        }

        function adjustRelationshipListOnEnrollmentChange(enrolledDependentList) {
            if (isSpouseOrLifePartnerAlreadyEnrolled(enrolledDependentList)) {
                vm.relationshipList = removeSpouseOrLifePartnerFromRelationshipDropDownWhenAlreadyEnrolled(vm.relationshipListPristine);
            }
            else {
                vm.relationshipList = vm.relationshipListPristine;
            }
        }

        function isSpouseOrLifePartnerAlreadyEnrolled(enrolledDependentsList) {
            return enrolledDependentsList.some(enrollee => enrollee.relationshipCode === RELATIONSHIP_LIFE_PARTNER || enrollee.relationshipCode === RELATIONSHIP_SPOUSE);
        }

        function removeSpouseOrLifePartnerFromRelationshipDropDownWhenAlreadyEnrolled(relationshipList) {
            return relationshipList.filter(relationship => relationship.value == RELATIONSHIP_CHILD);
        }

        function setInitialValuesForStep2() {
            if (vm.isInitialCallToGetDependentsNotOnCurrentPlan) {
                vm.isInitialCallToGetDependentsNotOnCurrentPlan = false;
                getEnrolleeDependents();
            }

            adjustRelationshipListOnEnrollmentChange(vm.enrolledDependentList);
        }

        function getMemberListForBillingSummary() {
            const primarySubscriber = vm.originalPlans[0].members.find(member => member.relationshipCode === RELATIONSHIP_SELF);

            return [primarySubscriber, ...vm.enrolledDependentList];
        }

        function updatePremiumTypeOnEnrollmentChange() {
            const payload = {
                premiumGroupId: vm.premiumGroup,
                productId: vm.selectedProduct.productId,
                spouseFlag: planManagementApiService.isSpouseCurrentlyEnrolled(vm.enrolledDependentList),
                childCount: planManagementApiService.getChildCount(vm.enrolledDependentList),
                effectiveDate: vm.effectiveDate
            };

            planManagementApiService.updatePremiumTypeOnEnrollmentChange(payload, vm.premiumTypeList).then(response => {
                if (!response) {
                    return;
                }
                vm.selectedPremiumType = response;
            });
        }
    }
})();;
(function () {
    "use strict";
    angular
        .module("MWPApp")
        .component("noAdditionalPlanModal", {
            controller: noAdditionalPlanModalController,
            controllerAs: "vm",
            templateUrl: "/MWP/Template/NoAdditionalPlanModal",
            bindings: {
                modalInstance: "<"
            }
        })

    noAdditionalPlanModalController.$inject = [];

    function noAdditionalPlanModalController() {
        let vm = this;

        vm.cancel = cancel;

        function cancel() {
            vm.modalInstance.close("close");
        }
    }
})();;
(function () {
    "use strict";
    angular
        .module("MWPApp")
        .component("planManagement", {
            templateUrl: "planManagementTemplate",
            controller: planManagementController,
            controllerAs: "vm",
            bindings: {

            }
        });
    planManagementController.$inject = ["$state", "$translate", "PlanManagementApiService", "WbxModalService", "ImpersonateService", "$scope", "DataService", "TerminateModalService", "$rootScope"];
    function planManagementController($state, $translate, planManagementApiService, wbxModalService, impersonateService, $scope, dataService, terminateModalService, $rootScope) {
        let vm = this;
        const BILLING_CICLE_TYPE_MONTHLY = 1;
        const BILLING_CICLE_TYPE_ANNUAL = 4;
        const LIFE_INSURANCE_LINE_OF_BUSINESS = 9;
        vm.billingCycleTypeMonthly = BILLING_CICLE_TYPE_MONTHLY;
        vm.billingCycleTypeAnnual = BILLING_CICLE_TYPE_ANNUAL;
        vm.planTypes = [];
        vm.insuredEnrollee = {};
        vm.members = [];
        vm.$onInit = $onInit;
        vm.getMembersOnPlanCommaSeparated = getMembersOnPlanCommaSeparated;
        vm.getTranslationWithParam = getTranslationWithParam;
        vm.addNewPlanButton = addNewPlanButton;
        vm.changePlanButton = changePlanButton;
        vm.openTerminateContractModal = openTerminateContractModal;
        vm.getToolipForNoPlansForLineOfBusiness = getToolipForNoPlansForLineOfBusiness;
        vm.getToolTipForNoTerminateFuturePlans = getToolTipForNoTerminateFuturePlans;
        vm.isFuturePlan = false;

        function $onInit() {
            setPageTitle($translate.instant("PlanManagement_Title"));
            impersonateService.getImpersonateSessionInfo()
                .then(function (response) {
                    vm.isImpersonation = response.IsImpersonation;
                });
            getCoverage();
        }

        function getMembersOnPlanCommaSeparated(members) {
            let membersResult = members.map(function (member) {
                return [`${member.firstName} ${member.lastName}`];
            }).join(", ");
            return membersResult || "";
        }

        function getTranslationWithParam() {
            return { lastDayOpenEnrollment: vm.openEnrollment.endDate };
        }

        function addNewPlanButton() {

            planManagementApiService.getPlans(vm.planTypes, dataService.GroupId, vm.openEnrollment.renewDate)
                .then(function (response) {
                    if (response.data.length != 0) {
                        $state.go("addNewPlanPage", {
                            planTypes: vm.planTypes,
                            effectiveDate: vm.openEnrollment.renewDate,
                            premiumGroup: dataService.GroupId,
                            insuredEnrollee: vm.insuredEnrollee,
                            dependents: vm.members,
                            subscriberPlans: vm.plans,
                            billingCycleType: vm.billingCycleType 
                        });
                    } else {
                        noAdditionalPlan();
                    }
                });
        }

        function changePlanButton(planSelected) {
            $state.go("changePlanPage", {
                effectiveDate: vm.openEnrollment.renewDate,
                planSelected: planSelected,
                premiumGroup: dataService.GroupId,
                dependents: planSelected.members,
                subscriberPlans: vm.plans,
                billingCycleType: vm.billingCycleType
            });
        }

        function setPageTitle(title) {
            document.title = title;
        }
        function getTotalsGivenPlans(plans) {
            if (!plans) {
                return null;
            }

            const initialValue = {
                frequencyTotals: 0,
                billingFrequencyDiscounts: 0,
                paymentMethodDiscounts: 0
            };

            const result = plans.reduce((accum, curr) => {
                accum.frequencyTotals += curr.frequencyTotal;
                accum.billingFrequencyDiscounts += curr.billingFrequencyDiscount;
                accum.paymentMethodDiscounts += curr.paymentMethodDiscount;

                return accum;
            }, initialValue);

            const totals = {
                total: result.frequencyTotals,
                billingFrequencyDiscount: result.billingFrequencyDiscounts,
                paymentMethodDiscount: result.paymentMethodDiscounts,
                totalAmountBilled: result.frequencyTotals - (result.billingFrequencyDiscounts + result.paymentMethodDiscounts)
            };

            return totals;
        }

        function getCoverage() {
            planManagementApiService.getCoverage()
                .then(function (response) {
                    const plans = response.data.plans.filter(plan => plan.lineOfBusiness != LIFE_INSURANCE_LINE_OF_BUSINESS && !plan.hasCurrentPlanAlreadyBeenTerminated)
                    vm.planTypes = getPlanTypes(response.data.plans);
                    vm.members = processMembersAndInsuredEnrollee(response.data.plans);
                    vm.openEnrollment = response.data.openEnrollment;
                    vm.plans = plans;
                    vm.isDataMissing = vm.plans.length === 0;
                    vm.isSubscriber = response.data.isSubscriber;
                    vm.billingCycleType = response.data.billingCycleType;
                    vm.totals = getTotalsGivenPlans(plans);
                });
        }

        function openTerminateContractModal() {
                let modalDefaults = {
                    backdrop: "static",
                    keyboard: true,
                    modalFade: true,
                    component: "terminateModalComponent",
                    size: "lg",
                    windowClass: "",
                    resolve: {
                        payload: {
                            isComingFromPlanManagement: true
                        }
                    }
                };
                wbxModalService.showModal(modalDefaults, {});
        }

        function noAdditionalPlan() {
            let modalDefaults = {
                component: "noAdditionalPlanModal",
                size: "lg",
                windowClass: "",
                resolve: {}
            };
            wbxModalService.showModal(modalDefaults);
        }

        function getToolipForNoPlansForLineOfBusiness(hasPlansForLineOfBusiness) {
            return !hasPlansForLineOfBusiness ? "PlanManagement_NoPlansForLineOfBusiness" : "";
        }

        function getToolTipForNoTerminateFuturePlans(isFuturePlan) {
            return isFuturePlan ? 'PlanManagement_TerminateButton_UnableToTerminateFuturePlan' : "";
        }

        function getPlanTypes(plans) {
            let planTypes = plans.map(plan => {
                if (!plan.hasCurrentPlanAlreadyBeenTerminated) {
                    return plan.planType;
                }
            })

            return planTypes.filter(x => x != undefined)
        }

        function processMembersAndInsuredEnrollee(plans) {
            let allMembers = plans.flatMap(plan => plan.members.flatMap(member => {
                if (member.memberId == '00') {
                    vm.insuredEnrollee = member
                }
                else {
                    return member;
                }
            }));

            return allMembers.filter(x => x !== undefined);
        }

        $scope.$on('terminateSubscriber', function (event, responseTerminateSubscriber) {
            vm.terminateSubscriberSuccessful = responseTerminateSubscriber.IsSusbcriberTerminate;

            if (!vm.terminateSubscriberSuccessful) return;

            getCoverage();
        });
    }
})();;
//(function () {
//    'use strict';
//    angular
//        .module('MWPApp')
//        .component('ComponentName', {
//            templateUrl: '/Shared/ComponentTemplate',
//            controller: ComponentController,
//            controllerAs: 'vm',
//            bindings: {
//                param: '='
//            }
//        });

//    ComponentController.$inject = ['$http'];
//    function ComponentController($http) {
//        var vm = this;
        
//    }

//})();
;
(function () {
    'use strict';
    angular
        .module('MWPApp')
        .service("AccumulatorInformationService", accumulatorInformationService);

    accumulatorInformationService.$inject = ['API'];

    function accumulatorInformationService(api) {
        return {
            getAccumulatorInformationDetail: getAccumulatorInformationDetail
           
        };
        function getAccumulatorInformationDetail(payload) {
            return api.get("/MWP/Accumulator/GetAccumulatorInformationDetailByEnrolleeId", payload)
                .then(response=> response.data);
        }
    }
})();;
(function () {
    'use strict';
    angular.module('MWPApp')
        .service("BeneficiaryDesignationService", BeneficiaryDesignationService);

    BeneficiaryDesignationService.$inject = ['API'];

    function BeneficiaryDesignationService(api) {
        return {
            showBeneficiaryDesignationBanner
        };

        function showBeneficiaryDesignationBanner() {
            return api.get('/MWP/Beneficiaries/ShowBeneficiaryDesignationBanner')
                .then(function (response) {
                    return response.data;
                });
        }
    }
})();;
(function () {
    "use strict";
    angular.module("MWPApp")
        .service("TerminateModalService", TerminateModalService);

    TerminateModalService.$inject = ["API"];

    function TerminateModalService(API) {
        return {
            getQualifyingEventsTerminateContract: getQualifyingEventsTerminateContract,
            getEnrolleeActivePlans: getEnrolleeActivePlans,
            validateTerminateSubscriber: validateTerminateSubscriber,
            terminateSubscriber: terminateSubscriber
        };

        function getQualifyingEventsTerminateContract(isOpenEnrollment = false) {
            return API.get("/MWP/Contract/GetQualifyingEventsTerminateContract", { isOpenEnrollment: isOpenEnrollment })
                .then(function (response) {
                    return response.data;
                });
        }

        function getEnrolleeActivePlans(enrolleeId) {
            return API.get("/MWP/EnrollmentSummary/GetEnrolleeActivePlans", { enrolleeId: enrolleeId })
                .then(function (response) {
                    return response.data;
                });
        }

        function validateTerminateSubscriber(subscriber) {
            return API.post("/MWP/Contract/ValidateTerminateSubscriber", subscriber)
                .then(function (response) {
                    return response;
                });
        }

        function terminateSubscriber(terminateSubscriberInput) {
            return API.post("/MWP/Contract/TerminateSubscriber", { terminateSubscriberInput: terminateSubscriberInput })
                .then(function (response) {
                    return response.data;
                });
        }
    }
})();;
(function () {
    "use strict";
    angular.module("MWPApp")
        .service("TerminateSubscriberConfirmationModalService", TerminateSubscriberConfirmationModalService);

    TerminateSubscriberConfirmationModalService.$inject = ["API"];

    function TerminateSubscriberConfirmationModalService(API) {
        return {
            getActiveFamilyMembers: getActiveFamilyMembers,
            validateTerminateSubscriber: validateTerminateSubscriber
        };

        function getActiveFamilyMembers(products) {
            return API.get("/MWP/EnrollmentSummary/GetActiveFamilyMembers", { products: products })
                .then(function (response) {
                    return response.data;
                });
        }

        function validateTerminateSubscriber(subscriber) {
            return API.post("/MWP/Contract/ValidateTerminateSubscriber", subscriber)
                .then(function (response) {
                    return response;
                });
        }
    }
})();;
(function () {
    'use strict';
    angular.module('MWPApp')
        .service("OpenEnrollmentService", OpenEnrollmentService);

    OpenEnrollmentService.$inject = ['API'];

    function OpenEnrollmentService(api) {
        return {
            getIsOpenEnrollment: getIsOpenEnrollment,
            getPortalInfo: getPortalInfo
        };

        function getIsOpenEnrollment() {
            return api.get('/MWP/IndividualEnrollment/IsOpenEnrollment')
                .then(function (response) {
                    return response.data;
                });
        }

        function getPortalInfo() {
            return api.get('/MWP/IndividualEnrollment/GetPortalInfo')
                .then(function (response) {
                    return response.data;
                });
        }
    }
})();;
(function () {
    "use strict";
    angular
        .module("MWPApp")
        .service("PaymentMethodService", PaymentMethodService);

    PaymentMethodService.$inject = ["API"];

    function PaymentMethodService(API) {
        return {
            getEnrolleePaymentMethod,
            getPaymentMethod,
            getAllEnrolleePaymentMethods,
            getEnrolleePaymentGateway,
            updateEnrolleePaymentMethod,
            addAuthorizeNetEnrolleePaymentMethod,
            addAuthorizeNetEnrolleePaymentMethodInternal,
            addStripeEnrolleePaymentMethod,
            deleteEnrolleePaymentMethod,
            createCustomerAndSetupIntent,
            createSetupIntent
        };

        function getEnrolleePaymentMethod() {
            return API.get("/MWP/PaymentMethod/GetEnrolleePaymentMethod");
        }

        function getPaymentMethod() {
            return API.get("/MWP/PaymentMethod/GetPaymentMethod");
        }

        function getAllEnrolleePaymentMethods() {
            return API.get("/MWP/PaymentMethod/GetAllEnrolleePaymentMethods");
        }

        function getEnrolleePaymentGateway() {
            return API.get("/MWP/PaymentMethod/GetEnrolleePaymentGateway")
                .then(function (response) {
                    return response.data;
                });
        }

        function updateEnrolleePaymentMethod(enrolleePaymentMethodId) {
            return API.post("/MWP/PaymentMethod/UpdateEnrolleePaymentMethod", {
                enrolleePaymentMethodId
            }).then(function (response) {
                return response.data;
            });
        }

        function addAuthorizeNetEnrolleePaymentMethod(paymentMethodData) {
            return API.post(
                "/MWP/PaymentMethod/AddAuthorizeNetEnrolleePaymentMethod",
                {
                    paymentMethodData,
                }
            ).then(function (response) {
                return response.data;
            });
        }

        function addAuthorizeNetEnrolleePaymentMethodInternal(paymentMethodData) {
            return API.post(
                "/MWP/PaymentMethod/AddAuthorizeNetEnrolleePaymentMethodInternal",
                {
                    paymentMethodData,
                }
            ).then(function (response) {
                return response.data;
            });
        }

        /**
         *
         * @param {{ paymentMethod: 'CreditCard'|'ACH', paymentGatewayId: number, paymentMethodId: string, paymentCustomerId: string }} param0
         * @returns {Promise<any>}
         */
        function addStripeEnrolleePaymentMethod({
            paymentMethod,
            paymentGatewayId,
            paymentGatewayPaymentMethodId,
            paymentGatewayCustomerId,
        }) {
            return API.post("/MWP/PaymentMethod/AddStripeEnrolleePaymentMethod", {
                paymentMethod,
                paymentGatewayId,
                paymentGatewayPaymentMethodId,
                paymentGatewayCustomerId,
            }).then((response) => response.data);
        }

        function deleteEnrolleePaymentMethod(enrolleePaymentMethodId) {
            return API.post("/MWP/PaymentMethod/DeleteEnrolleePaymentMethod", {
                enrolleePaymentMethodId
            }).then(function (response) {
                return response.data;
            });
        }

        function createCustomerAndSetupIntent(paymentGatewayId, name, email) {
            return API.post("/MWP/PaymentMethod/CreateCustomerAndSetupIntent", {
                paymentGatewayId,
                name,
                email,
            }).then(function (response) {
                return response.data;
            });
        }

        function createSetupIntent(paymentGatewayId, customerId) {
            return API.post("/MWP/PaymentMethod/CreateSetupIntent", {
                paymentGatewayId,
                customerId,
            }).then(function (response) {
                return response.data;
            });
        }
    }
})();
;
(function () {
    'use strict';
    angular
        .module('MWPApp')
        .service("AuthorizationCenterCtrlService", AuthorizationCenterCtrlService);

    AuthorizationCenterCtrlService.$inject = ['API', '$window', '$q'];
    function AuthorizationCenterCtrlService(API, $window, $q) {
        var vm = this;
        vm.submit = function (authInformation) {
            var deferred = $q.defer();
            API.put('/MWP/AuthorizationCenter/AuthorizationSearch',
                {
                    EnrolleeId: authInformation.EnrolleeId,
                    PeriodBegin: authInformation.PeriodBegin,
                    PeriodEnd: authInformation.PeriodEnd
                }).then(function (success) {
                    deferred.resolve(success);
                },
                    function (failed) {
                        deferred.reject(failed);
                        vm.authorizationcenter_form.$setPristine();
                    });
            return deferred.promise;
        }
    }
})();;
(function () {
    'use strict';
    angular
        .module('MWPApp')
        .service('BeneficiariesService', BeneficiariesService);

    BeneficiariesService.$inject = ['API'];

    function BeneficiariesService(api) {
        return {
            isLifeInsuranceProduct,
            getBeneficiaries,
            deleteBeneficiary,
            addBeneficiary,
            editBeneficiary
        };

        function isLifeInsuranceProduct() {
            return api.get('/MWP/Beneficiaries/IsLifeInsuranceProduct')
                .then(function (response) {
                    return response.data;
                });
        }

        function getBeneficiaries(beneficiariesInput) {
            return api.get('/MWP/Beneficiaries/GetBeneficiaries', beneficiariesInput)
                .then(function (response) {
                    return response.data;
                });
        }

        function deleteBeneficiary(beneficiary) {
            return api.post('/MWP/Beneficiaries/DeleteBeneficiary', beneficiary)
                .then(function (response) {
                    return response;
                });
        }

        function addBeneficiary(beneficiary) {
            return api.post('/MWP/Beneficiaries/AddBeneficiary', beneficiary)
                .then(function (response) {
                    return response.data;
                });
        }

        function editBeneficiary(beneficiary) {
            return api.post('/MWP/Beneficiaries/EditBeneficiary', beneficiary)
                .then(function (response) {
                    return response.data;
                });
        }
    }
})();;
(function () {
    'use strict';
    angular.module('MWPApp')
        .service("BenefitSummaryService", BenefitSummaryService);

    BenefitSummaryService.$inject = ['API'];

    function BenefitSummaryService(API) {
        return {
            getCustomBenefitSummaryReport: getCustomBenefitSummaryReport
        };


        function getCustomBenefitSummaryReport() {
            return API.get('/MWP/EnrollmentSummary/GetCustomBenefitSummaryReport', {}, { responseType: "blob" });
        }

    }
})();;
(function () {
    'use strict';
    angular
        .module('MWPApp')
        .service('BillingInformationService', BillingInformationService);

    BillingInformationService.$inject = ['API'];

    function BillingInformationService(api) {
        var vm = this;
        vm.getBillingHistory = getBillingHistory;
        vm.getContractHistory = getContractHistory;
        vm.updateBillingFrequency = updateBillingFrequency;
        vm.getBillingCycleMonthlyAndAnnually = getBillingCycleMonthlyAndAnnually;
        vm.isDependent = isDependent;
        vm.hasIndividualPaymentMethods = hasIndividualPaymentMethods;

        function getBillingHistory() {
            return api.get('/MWP/BillingInformation/GetBillingHistory')
                .then(function (response) {
                    return response.data;
                });
        }


        function getContractHistory() {
            return api.get('/MWP/BillingInformation/GetContractHistory')
                .then(function (response) {
                    return response.data;
                });
        }

        function updateBillingFrequency(billingCycleType) {
            return api.post('/MWP/BillingInformation/UpdateBillingFrequency', { billingCycleType: billingCycleType })
                .then(function (response) {
                    return response.data;
                });
        }

        function getBillingCycleMonthlyAndAnnually() {
            return api.get('/MWP/BillingInformation/GetBillingCycleMonthlyAndAnnually')
                .then(function (response) {
                    return response.data;
                });
        }

        function isDependent() {
            return api.get('/MWP/BillingInformation/IsDependent')
                .then(function (response) {
                    return response.data;
                });
        }

        function hasIndividualPaymentMethods() {
            return api.get("/MWP/BillingInformation/HasIndividualPaymentMethods")
                .then(function (response) {
                    return response.data;
                });
        }
    }
})();;
(function () {
    'use strict';
    angular
        .module('MWPApp')
        .service("ClaimCenterCtrlService", ClaimCenterCtrlService);

    ClaimCenterCtrlService.$inject = ['API', '$window', '$q'];
    function ClaimCenterCtrlService(API, $window, $q) {
        var vm = this;
        vm.submit = function (claimInformation) {
            var deferred = $q.defer();
            API.put('/MWP/ClaimCenter/ClaimSearch',
            {
                EnrolleeId: claimInformation.EnrolleeId,
                PeriodBegin: claimInformation.PeriodBegin,
                PeriodEnd: claimInformation.PeriodEnd
            }).then(function (success) {
                deferred.resolve(success);
            },
                    function (failed) {
                        deferred.reject(failed);
                        vm.claimcenter_form.$setPristine();
                    });
            return deferred.promise;
        }
    }
})();;
(function () {
    'use strict';
    angular
        .module('MWPApp')
        .service("DocumentsService", DocumentsService);

    DocumentsService.$inject = ['API', '$q'];
    function DocumentsService(API, $q) {
        var vm = this;

        //vm.init = function () {
        //    var deferred = $q.defer();
        //    API.get('/MWP/Documents/GetDocuments/')
        //     .then(function (success) {
        //         deferred.resolve(success);
        //     },
        //         function (failed) {
        //             deferred.reject(failed);
        //         });
        //    return deferred.promise;
        //}

        vm.logViewDocument = function (documentId, isInstantEOB) {
            var deferred = $q.defer();
            if (isInstantEOB) {
                API.put('/MWP/Documents/LogInstantEOBView?documentId=' + documentId)
                    .then(function (success) {
                        deferred.resolve(success);
                    },
                        function (failed) {
                            deferred.reject(failed);
                        });
            } else {
                API.put('/MWP/Documents/LogView?documentId=' + documentId)
                    .then(function (success) {
                        deferred.resolve(success);
                    },
                        function (failed) {
                            deferred.reject(failed);
                        });
            }

            return deferred.promise;
        };
    }
})();;
(function () {
    'use strict';
    angular.module('MWPApp')
        .service("AddDependentConfirmationModalService", AddDependentConfirmationModalService);

    AddDependentConfirmationModalService.$inject = ['API'];

    function AddDependentConfirmationModalService(API) {
        return {
            validateAddDependent: validateAddDependent
        };

        function validateAddDependent(payload) {
            return API.post('/MWP/EnrollmentSummary/ValidateAddDependent', payload)
                .then(function (response) {
                    return response;
                });
        }
    }
})();;
(function () {
    'use strict';
    angular.module('MWPApp')
        .service("EnrollmentSummaryService", EnrollmentSummaryService);

    EnrollmentSummaryService.$inject = ['API', '$window', '$q'];

    function EnrollmentSummaryService(API, $window, $q) {
        var vm = this;
        vm.baseUrl = '/MWP/EnrollmentSummary/'

        vm.hasApiSetup = function () {
            return API.get(vm.baseUrl + 'HasApiSetup')
        }

        vm.getCustomBenefitSummaryReport = function () {
            return API.get(vm.baseUrl + 'GetCustomBenefitSummaryReport', {}, { responseType: "blob" });
        }


        vm.getEscalationTier = function (payload) {
            return API.get(vm.baseUrl + 'GetEscalationTier', payload)
        }

        vm.addDependent = function (payload) {
            return API.post(vm.baseUrl + 'addDependent', payload);
        };

        vm.getMaritalStatuses = function (enrolleeId) {
            var deferred = $q.defer();
            API.get('/Enrollee/GetMaritalStatuses')
                .then(
                    function (ok) {
                        deferred.resolve(ok);
                    },
                    function (failed) {
                        deferred.reject(failed);
                    });
            return deferred.promise;
        }

        vm.getAddReasonCodesForDependent = function (isOpenEnrollment = true) {
            var deferred = $q.defer();
            API.get(vm.baseUrl + 'GetAddReasonCodesForDependentMWP?isOpenEnrollment=' + isOpenEnrollment)
                .then(
                    function (ok) {
                        deferred.resolve(ok);
                    },
                    function (failed) {
                        deferred.reject(failed);
                    });
            return deferred.promise;
        };

        vm.getRelationshipCodesAddDependent = function () {
            var deferred = $q.defer();
            API.get(vm.baseUrl + 'GetRelationshipCodesAddDependent')
                .then(
                    function (ok) {
                        deferred.resolve(ok);
                    },
                    function (failed) {
                        deferred.reject(failed);
                    });
            return deferred.promise;
        };

        vm.getMemberSSN = function (enrolleeId) {
            var deferred = $q.defer();
            API.get(vm.baseUrl + 'GetMemberSSN?enrolleeId=' + enrolleeId)
                .then(
                    function (ok) {
                        deferred.resolve(ok);
                    },
                    function (failed) {
                        deferred.reject(failed);
                    });
            return deferred.promise;
        }


        vm.getMemberInfo = function (enrolleeId) {
            var deferred = $q.defer();
            API.get(vm.baseUrl + 'GetMemberInfo?enrolleeId=' + enrolleeId)
                .then(
                    function (ok) {
                        deferred.resolve(ok);
                    },
                    function (failed) {
                        deferred.reject(failed);
                    });
            return deferred.promise;
        }

        vm.requestIdCard = function () {
            var deferred = $q.defer();
            API.put('/MWP/RequestID/RequestCard').then(
                function (success) {
                    if (success.Status)
                        deferred.resolve();
                    else
                        deferred.reject();
                });
            return deferred.promise;
        }

        vm.getStateList = function () {
            var deferred = $q.defer();
            API.get('/PortalDropList/GetStates')
                .then(
                    function (ok) {
                        deferred.resolve(ok);
                    },
                    function (failed) {
                        deferred.reject(failed);
                    });
            return deferred.promise;
        };

        vm.getPolicyHoldersCurrentActivePlans = function (payload) {
            return API.post(vm.baseUrl + 'GetPolicyHoldersCurrentActivePlans', payload);
        };

        vm.saveEdit = function (enrolleeInfo) {
            var deferred = $q.defer();

            API.post(vm.baseUrl + 'SaveEdit',
                {
                    ENROLLEE_ID: enrolleeInfo.ENROLLEE_ID,
                    FIRST_NAME: enrolleeInfo.FIRST_NAME,
                    MIDDLE_NAME: enrolleeInfo.MIDDLE_NAME,
                    LAST_NAME: enrolleeInfo.LAST_NAME,
                    DOB: enrolleeInfo.DOB,
                    GENDER: enrolleeInfo.GENDER,
                    SS_NUMBER: enrolleeInfo.SS_NUMBER,
                    MARITAL_STATUS: enrolleeInfo.MARITAL_STATUS,
                    HANDICAP_FLAG: enrolleeInfo.HANDICAP_FLAG,
                    ADDRESS1: enrolleeInfo.ADDRESS1,
                    ADDRESS2: enrolleeInfo.ADDRESS2,
                    CITY: enrolleeInfo.CITY,
                    STATE: enrolleeInfo.STATE,
                    ZIP: enrolleeInfo.ZIP,
                    ZIP_4: enrolleeInfo.ZIP_4,
                    PHONE_NUMBER: enrolleeInfo.PHONE_NUMBER,
                    PHONE_EXTENSION: enrolleeInfo.PHONE_EXTENSION,
                    APPLY_TO_ALL: enrolleeInfo.APPLY_TO_ALL
                })
                .then(
                    function (ok) {
                        deferred.resolve(true);
                    },
                    function (failed) {
                        deferred.reject(failed);
                    });

            return deferred.promise;
        }

        vm.isIndividualEnrollment = function () {
            var deferred = $q.defer();
            API.get(vm.baseUrl + 'IsIndividualEnrollment')
                .then(
                    function (ok) {
                        deferred.resolve(ok);
                    },
                    function (failed) {
                        deferred.reject(failed);
                    });
            return deferred.promise;
        }

        vm.canAddDependents = function (payload) {
            var deferred = $q.defer();
            API.get(vm.baseUrl + 'CanAddDependents', payload)
                .then(
                    function (ok) {
                        deferred.resolve(ok);
                    },
                    function (failed) {
                        deferred.reject(failed);
                    });
            return deferred.promise;
        }

        vm.getQualifyingEventsRemoveDependent = function (isOpenEnrollment = true) {
            var deferred = $q.defer();
            API.get(vm.baseUrl + 'GetQualifyingEventsRemoveDependent?isOpenEnrollment=' + isOpenEnrollment)
                .then(
                    function (ok) {
                        deferred.resolve(ok);
                    },
                    function (failed) {
                        deferred.reject(failed);
                    });
            return deferred.promise;
        };

        vm.getEnrolleePlans = function (enrolleeId) {
            var deferred = $q.defer();
            API.get(vm.baseUrl + 'GetEnrolleePlans?enrolleeId=' + enrolleeId)
                .then(
                    function (ok) {
                        deferred.resolve(ok);
                    },
                    function (failed) {
                        deferred.reject(failed);
                    });
            return deferred.promise;
        }

        vm.validateDropDependent = function (dependent) {
            var deferred = $q.defer();
            API.post(vm.baseUrl + 'ValidateDropDependent', dependent)
                .then(
                    function (ok) {
                        deferred.resolve(ok);
                    },
                    function (failed) {
                        deferred.reject(failed);
                    });

            return deferred.promise;
        }

        vm.dropDependent = function (dependent) {
            return API.post(vm.baseUrl + 'DropDependent', dependent)
                .then(function (response) {
                    return response.data;
                });
        }

        vm.getEnrolleeDependents = function (enrolleeDependentsInputDTO) {
            return API.post(vm.baseUrl + 'GetEnrolleeDependents', enrolleeDependentsInputDTO);
        };

        vm.getEnrolleeBillingCycleType = function () {
            return API.get(vm.baseUrl + 'GetEnrolleeBillingCycleType')
                .then(function (response) {
                    return response.data;
                });
        };

        vm.isCurrentDateAfter19thOfTheLastMonthFromCurrentContract = function (payload) {
            return API.get(vm.baseUrl + 'IsCurrentDateAfter19thOfTheLastMonthFromCurrentContract', payload)
                .then(function (response) {
                    return response.data;
                });
        };

        vm.canDropDependents = function (payload) {
            return API.get(vm.baseUrl + 'CanDropDependents', payload)
                .then(function (response) {
                    return response.data;
                });
        };

        vm.validateAddDependent = function (payload) {
            return API.post(vm.baseUrl + 'ValidateAddDependent', payload)
                .then(function (response) {
                    return response;
                });
        }

        vm.getDropDependentInfo = function (premiumGroupId) {
            return API.get(vm.baseUrl + 'GetDropDependentInfo')
                .then(function (response) {
                    return response.data;
                });
        };        

        vm.getCurrentEnrolleeContract = function () {
            return API.get(vm.baseUrl + 'GetCurrentEnrolleeContract')
                .then(function (response) {
                    return response.data;
                });
        }

        vm.preValidateAddDependent = function (payload) {
            return API.post(vm.baseUrl + 'PreValidateAddDependent', payload)
                .then(function (response) {
                    return response;
                });
        }
    }
})();;
(function () {
    'use strict';
    angular.module('MWPApp')
        .service("UpdateEscalationTierModalService", updateEscalationTierModalService);

    updateEscalationTierModalService.$inject = ['API'];

    function updateEscalationTierModalService(api) {
        const BASE_URL = '/MWP/EnrollmentSummary';
        return {
            updateEsclationTierDocuments: updateEsclationTierDocuments
        };

        function updateEsclationTierDocuments(payload) {
            return api.post(`${BASE_URL}/UpdateEsclationTierDocuments`, payload)
        }
    }
})();;
(function () {
    "use strict";
    angular.module("MWPApp")
        .service("PlanManagementApiService", PlanManagementApiService);

    PlanManagementApiService.$inject = ["API"];

    function PlanManagementApiService(API) {
        const RELATIONSHIP_SPOUSE = "01";
        const RELATIONSHIP_LIFE_PARTNER = "53";
        const RELATIONSHIP_CHILD = "19";
        const genderList = [
            {
                Value: 'F',
                Text: "GENDER_F"
            },
            {
                Value: 'M',
                Text: "GENDER_M"
            },
            {
                Value: 'U',
                Text: "GENDER_U"
            }
        ];
        return {
            GENDER_DROPDOWN_OPTIONS: genderList,
            getCoverage,
            getPlans,
            getPlansToChange,
            getGenders,
            getRelationshipList,
            getStateList,
            isDuplicateDependent,
            submitNewPlan,
            submitChangePlan,
            getBillingSummary,
            doesDependentCombinationMapToPremiumType,
            getSubscriberDetails,
            getEnrolleeDependents,
            processEnrollDependentFromStep2,
            removeDependentFromEnrollmentList,
            getChildCount,
            getPremiumTypeMapping,
            isSpouseCurrentlyEnrolled,
            updatePremiumTypeOnEnrollmentChange,
            isNewDependentAlreadyInEnrolledList
        };

        function getCoverage() {
            return API.get("/MWP/PlanManagement/GetCoverage");
        }

        function getPlans(planTypeTofilter, groupId, effectiveDate) {
            return API.get("/MWP/PlanManagement/GetPlansTypesWithProducts", { planTypeTofilter, groupId, effectiveDate });
        }

        function getPlansToChange(effectiveDate, lineOfBusiness, groupId, productId ) {
            return API.get("/MWP/PlanManagement/GetPlansToChange", { effectiveDate, lineOfBusiness, groupId, productId });
        }

        function getGenders() {
            return API.get("/PortalDropList/GetGenders").then(response => {
                return response.slice(1);
            });
        }

        function getRelationshipList() {
            return API.get("/Enrollee/getRelationshipCodes")
                .then(function (response) {
                    let list = [];
                    _.map(response, function (item) {
                        list.push({ value: item.RELATIONSHIP_CODE, text: `RELATIONSHIP_CODES_${item.RELATIONSHIP_CODE}`});
                    })
                    return { data: list };
                })
        };

        function getStateList() {
            return API.get("/PortalDropList/GetStates");
        }

        
        function isDuplicateDependent(payload) {
            return API.get("/MWP/PlanManagement/IsDuplicateDependent", payload);
        }

        function doesDependentCombinationMapToPremiumType(payload) {
            return API.post("/MWP/PlanManagement/DoesDependentCombinationMapToPremiumType", payload);
        }

        function submitNewPlan(payload) {
            return API.post("/MWP/PlanManagement/SubmitNewPlan", payload);
        }

        function submitChangePlan(payload) {
            return API.post("/MWP/PlanManagement/SubmitChangePlan", payload);
        }

        function getBillingSummary(plans, billingCycleType) {
            return API.post("/MWP/PlanManagement/GetBillingSummaryInformation", { plans, billingCycleType });
        }

        function getSubscriberDetails() {
            return API.get("/MWP/PlanManagement/GetSubscriberDetails");
        }

        function getDependentsAssociatedWithPrimaryEnrollee(payload) {
            return API.post("/MWP/PlanManagement/GetEnrolleeDependents", payload).then(response => {
                return (response.data && response.data.dependents || []);
            });
        }

        function getPremiumTypeMapping(payload) {
            return API.get("/MWP/PlanManagement/GetPremiumTypeContractTypeMapping", payload);
        }

        function getEnrolleeDependents(payload, dependentsAlreadyOnSelectedPlan = []) {
            return getDependentsAssociatedWithPrimaryEnrollee(payload).then(dependents => {
                const existingDependentIds = new Set(dependentsAlreadyOnSelectedPlan.map(e => e.enrolleeId));
                const dependentsAssociatedToPrimaryEnrollee = dependents.reduce((accum, dependentItem) => {
                    if (!existingDependentIds.has(dependentItem.enrolleeId)) {
                        accum.push({ ...dependentItem, dob: dependentItem.dateOfBirth });
                    }
                    return accum;
                }, []);

                return [...dependentsAssociatedToPrimaryEnrollee];
            }); 
        }

        function processEnrollDependentFromStep2(dependent, dependentsInDropdown, currentlyEnrolledDependentsInGrid, netNewDependents) {

            if (!dependent || (!dependent.isAllDependentsSelected && currentlyEnrolledDependentsInGrid.indexOf(dependent) > -1)) {
                return;
            }

            else if (dependent.enrolleeId === undefined) {
                const netNewDependentToAddToGrid = {
                    name: dependent.firstName + " " + dependent.lastName,
                    dob: dependent.dob,
                    memberId: undefined,
                    relationshipCode: dependent.relationshipCode,
                    relationshipDescription: dependent.relationshipDescription,
                    firstName: dependent.firstName,
                    lastName: dependent.lastName
                };
                currentlyEnrolledDependentsInGrid.push(netNewDependentToAddToGrid)
                netNewDependents.push(dependent);
            }

            else {
                currentlyEnrolledDependentsInGrid.push(dependent);
            }

            if (currentlyEnrolledDependentsInGrid) {
                let selectedEnrolleeIds = new Set(currentlyEnrolledDependentsInGrid.map(x => x.enrolleeId));
                dependentsInDropdown = [...dependentsInDropdown.filter(x => !selectedEnrolleeIds.has(x.enrolleeId))];
            }

            return { dependentsInDropdown, currentlyEnrolledDependentsInGrid, netNewDependents };
        }

        function isASpouseOrLifePartnerAlreadyEnrolled(currentlyEnrolledDependentsInGrid) {
            let test = currentlyEnrolledDependentsInGrid.some(d => d.relationshipCode == RELATIONSHIP_LIFE_PARTNER || d.relationshipCode == RELATIONSHIP_SPOUSE)
            return test;
        }

        function removeDependentFromEnrollmentList(dependent, dependentsInDropdown, currentlyEnrolledDependentsInGrid, netNewDependents) {
            if (dependent.enrolleeId && !dependentsInDropdown.includes(dependent)) {
                dependentsInDropdown.push(dependent);
            }

            let newDependentToRemoveFromGrid = netNewDependents.find(x => x.firstName === dependent.firstName && x.lastName === dependent.lastName && x.dob === dependent.dob && x.memberId === dependent.memberId);

            if (newDependentToRemoveFromGrid) {
                netNewDependents.splice(newDependentToRemoveFromGrid, 1);
            }

            let enrolledDependentToRemove = currentlyEnrolledDependentsInGrid.indexOf(dependent);
            currentlyEnrolledDependentsInGrid.splice(enrolledDependentToRemove, 1);

            return { dependentsInDropdown, currentlyEnrolledDependentsInGrid, netNewDependents };
        }

        function isAnySpouseInListOfDependentsToAdd(selectedDependent, listoFdependentsToCheck) {
            return listoFdependentsToCheck.some(enrollee => enrollee.relationshipCode == RELATIONSHIP_LIFE_PARTNER || enrollee.relationshipCode == RELATIONSHIP_SPOUSE);
        }

        function isNewDependentAlreadyInEnrolledList(currentlyEnrolledDependents, newDependentBase) {
            return currentlyEnrolledDependents.some(existingEnrollee => existingEnrollee.firstName == newDependentBase.firstName && existingEnrollee.lastName == newDependentBase.lastName && existingEnrollee.dob == newDependentBase.dob);
        }

        function getChildCount(enrolledDependentsList) {
            return enrolledDependentsList.filter(dependent => dependent.relationshipCode == RELATIONSHIP_CHILD).length;
        }

        function isSpouseCurrentlyEnrolled(enrolledDependentList) {
            return enrolledDependentList.some(enrollee => enrollee.relationshipCode == RELATIONSHIP_SPOUSE || enrollee.relationshipCode == RELATIONSHIP_LIFE_PARTNER);
        }

        function updatePremiumTypeOnEnrollmentChange(payload, premiumTypeList) {

            return getPremiumTypeMapping(payload).then(response => {
                if (!response.data) {
                    return;
                }
                const premiumTypeMapping = response.data;
                const selectedPremiumTypeFromMapping = premiumTypeList.find(premiumType => premiumType.premiumTypeId == premiumTypeMapping.premiumTypeId && premiumType.subscriberContractTypeIds.includes(premiumTypeMapping.subscriberContractType));

                if (!selectedPremiumTypeFromMapping) {
                    return;
                }

                return selectedPremiumTypeFromMapping.premiumTypeId;
            })
        }
    }
})();;
(function () {
    "use strict";
    angular.module("MWPApp")
        .service("PlanManagementService", PlanManagementService);

    function PlanManagementService() {
        return {
            getPlansForBillingSummary,
            displayDuplicateDepenentError,
            displayDependentCombinationError,
            displayDependentAgeCutoffError,
            displayOnlyOneSpouseAllowedError
        };

        function getPlansForBillingSummary(originalPlans, selectedPlan, productIdToTerminate) {
            const toPlan = p => ({
                ProductId: p.productId,
                EmbeddedLifeProductId: p.embeddedLifeProductId,
                PremiumGroupId: p.premiumGroupId,
                ProductDescription: p.planName,
                LineOfBusinessDescription: p.planType,
                MemberList: p.members
            });

            return [
                ...originalPlans.filter(plan => plan.productId != productIdToTerminate).map(toPlan),
                selectedPlan
            ];
        }
        function displayDuplicateDepenentError() {
            return true;
        }

        function displayDependentCombinationError() {
            return true;
        }

        function displayDependentAgeCutoffError() {
            return true;
        }

        function displayOnlyOneSpouseAllowedError() {
            return true
        }
    }
})();;
(function () {
    'use strict';
    angular
        .module('MWPApp')
        .service("PrintCardService", PrintCardService);

    PrintCardService.$inject = ['API'];

    function PrintCardService(API) {
        var vm = this;

       vm.UseUnum = function () {
           return API.get('/MWP/PrintIDCard/PortalUseUnumApi', {}, {});
        }

        
        vm.IdCardPdf = function () {
            return API.get('/MWP/PrintIDCard/GetUnumIdCardPdf', {}, { responseType: "blob" });
        }

    }
})();;
(function() {
    'use strict';
    angular
        .module('MWPApp')
        .service("SelectGroupService", SelectGroupService);

    SelectGroupService.$inject = ['API','$window', '$q'];

    function SelectGroupService(API, $window, $q) {
        var vm = this;

        vm.setPlan = function(groupId, planId, subscriberId) {
            var deferred = $q.defer();
            API.put('/MWP/SelectGroup/SelectGroup',
                {
                    groupId: groupId,
                    planId: planId,
                    subscriberId: subscriberId
                })
                .then(
                    function (ok) {
                        deferred.resolve(true);
                        //window.location = '/MWP/';
                    },
                    function(failed) {
                        deferred.reject(failed);
                    });
            return deferred.promise;
        }
    }
})();;
(function () {
    'use strict';
    angular
        .module('MWPApp')
        .service("AddDocumentService", AddDocumentService);

    AddDocumentService.$inject = ['API'];

    function AddDocumentService(API) {
        return {
            getFileUploadConfiguration: getFileUploadConfiguration,
            searchDocuments: searchDocuments,
            deleteDocument: deleteDocument
        };

        function getFileUploadConfiguration() {
            return API.get('/api/UploadApi/GetFileUploadConfiguration')
                .then(function (response) {
                    return response.data;
                });
        };

        function searchDocuments(searchDocumentInput) {
            return API.post('/api/UploadApi/SearchDocuments', searchDocumentInput)
                .then(function (response) {
                    return response.data;
                });
        };

        function deleteDocument(documentId, documentStatus) {
            var documentInput = {
                documentId: documentId,
                documentStatus: documentStatus
            };
            return API.post('/api/UploadApi/DeleteDocument', documentInput)
                .then(function (response) {
                    return response.data;
                });
        }
    }
})();;
(function () {
    'use strict';
    app.component('wbxChangePassword',
    {
        templateUrl: '/Templates/Password',
        controller: changePassword,
        controllerAs: 'vm',
        bindings: {
            passwordInfo: '=',
            changePasswordBtn: '@',
            currentPassword: '=', //For CurrentPassword Textbox
            resetPasswordBtn: '=', //For ResetPassword Page
            submitButton: '&',
            isPasswordTab: '=',
            isForgotPassword: '=?',
            successCallback: '=?',
            isImpersonation: '=?',
            isAuthenticatorAppEnabled: '=?',
            clickBackButton: '&?', //click function
            hideParentHeader: '&?', //click function
        }
    });

    changePassword.$inject = ['wbxChangePasswordService', '$scope', '$window', 'DataService', 'MultifactorService', '$timeout', 'API','wbxListErrorsService'];

    function changePassword(wbxChangePasswordService, $scope, $window, DataService, multifactorService, $timeout, api,wbxListErrorsService) {
        var vm = this;
        vm.PasswordInfo = {
            USER_NAME: "",
            NEW_PASSWORD: "",
            CONFIRM_PASSWORD: "",
            RESETPASS_VID: ""
        };
        vm.isPasswordValid = false;
        vm.showPasswordExpired = true;
        vm.displayVerifyYourIdentity = false;
        vm.IsMWP = DataService.IsMWP;
        vm.methodTypes = multifactorService.getMethodsEnum();
        
        if (vm.isAuthenticatorAppEnabled != null) {
            vm.isAuthenticatorAppEnabled = vm.isAuthenticatorAppEnabled;
        } else {
            vm.isAuthenticatorAppEnabled = DataService.Is2FAAuthenticatorAppEnabled;
        }

        vm.isAuthenticatorAppVerified = DataService.IsAuthenticatorAppVerified;

        vm.$onInit = function () {
            if (vm.isForgotPassword !== true)
                getMaskedEmail();

            vm.isEmailOn = DataService.IsEmailOn;
            vm.isSmsOn = DataService.IsSmsOn;
            vm.isAuthenticatorAppOn = DataService.IsAuthenticatorAppOn;

            if (vm.isEmailOn) {
                vm.selectedMethod = vm.methodTypes.email;
            }
            else if (vm.isSmsOn){
                vm.selectedMethod = vm.methodTypes.sms;
            }
            else if (vm.isAuthenticatorAppOn){
                vm.selectedMethod = vm.methodTypes.authenticator;
            }
        }

        vm.submit = function () {
            if (!vm.isImpersonation) {
                vm.showUnsuccessfulPasswordChange = false;
                if (vm.password_form.$invalid) {
                    vm.errors = wbxListErrorsService.getErrorListForBanner(vm.password_form)
                    return;
                }
                var promise = vm.isForgotPassword ? wbxChangePasswordService.validateResetPasswordInfo(vm.passwordInfo):
                              vm.isPasswordTab ? wbxChangePasswordService.validateChangePasswordInfo(vm.passwordInfo): 
                              wbxChangePasswordService.validateExpiredPasswordInfo(vm.passwordInfo);        
                promise.then(function successCallback(response) {
                    if (!response.Error) {
                        vm.verifyUserIdentity();
                    } else {
                        vm.passwordChangeMessage = response.Message;
                        vm.transKey = response.TranslationKey;
                        vm.showUnsuccessfulPasswordChange = vm.passwordChangeMessage === undefined ? false : true;
                    }
                    vm.password_form.$setPristine();
                });                
            }
        }

        vm.verifyUserIdentity = function () {
            vm.displayVerifyYourIdentity = true;
            vm.hideHeader();
        };

        vm.submitCodeAndChangePassword = function (code, method) {
            vm.passwordInfo.CODE = code;
            vm.passwordInfo.METHOD = method;
            vm.loginInfo = {
                UserName: vm.passwordInfo.USER_NAME,
                Password: vm.passwordInfo.NewPassword,
                RememberMe: false
            }
            //AccountManagement Password Tab
            if (vm.isPasswordTab) {
                return vm.changePasswordTab();
            }
            else
                // Reset Password Page
                if (vm.resetPasswordBtn) {
                    return vm.resetPassword();
                }
                else {
                    // Change Password Page
                    return vm.changePassword();
                }

        }
        vm.verifyYourIdentitySuccessCallback = function () {

            if (vm.showUnsuccessfulPasswordChange === false && angular.isFunction(vm.successCallback))
                vm.successCallback(vm.loginInfo);
        };
        
        // Gets called by AccountManagement change password 
        vm.changePasswordTab = function () {
if (!vm.isImpersonation)
{
            vm.showUnsuccessfulPasswordChange = false;
            vm.showPasswordUpdated = false;            
            var promise = wbxChangePasswordService.changePasswordWithCurrentPassword(vm.passwordInfo);
            promise.then(function successCallback(response) {
                if (!response.Error) {
                    vm.showPasswordUpdated = true;
                    vm.clearPasswordForm();
                } else {
                    vm.passwordChangeMessage = response.Message;
                    vm.transKey = response.TranslationKey;
                    vm.showUnsuccessfulPasswordChange = vm.passwordChangeMessage === undefined ? false : true;
                }
                vm.password_form.$setPristine();
                vm.displayVerifyYourIdentity = false;
                vm.showHeader();
                return response;
            });
            return promise;
}
        }
    
        // Called when password is expired
        vm.resetPassword = function () {
            var promise = wbxChangePasswordService.changeExpiredPasswordWithCurrentPassword(vm.passwordInfo);
            promise.then(function successCallback(response) {
                if (!response.Error) {
                    vm.showPasswordExpired = false;
                    vm.showPasswordUpdated = false;
                    if (DataService.mulipleGroupsPlans > 1) {
                        $window.location.href = "/MWP/SelectGroup/Index";
                    } else {
                        $window.location.href = "/MWP/Home/Index";
                    }
                    vm.clearPasswordForm();
                } else {
                    vm.showPasswordExpired = true;
                    vm.passwordChangeMessage = response.Message;
                    vm.transKey = response.TranslationKey;
                    vm.showUnsuccessfulPasswordChange = vm.passwordChangeMessage === undefined ? false : true;
                }
                vm.password_form.$setPristine();
                vm.displayVerifyYourIdentity = false;
                vm.showHeader();

                return response;
            },
                function (failed) {
                    //failed
                    throw failed;

                }).finally(function () {
                });
            return promise;

        }
        
        // Gets called when user is not logged in and forgot password
        vm.changePassword = function () {
            var promise = wbxChangePasswordService.changePassword(vm.passwordInfo);
            promise.then(function successCallback(response) {
                if (!response.Error) {
                    vm.showPasswordUpdated = true;
                } else {
                    vm.passwordChangeMessage = response.Message;
                    vm.transKey = response.TranslationKey;
                    vm.showUnsuccessfulPasswordChange = vm.passwordChangeMessage === undefined ? false : true;
                }
                vm.password_form.$setPristine();
                vm.displayVerifyYourIdentity = false;
                vm.showHeader();

                return response;
            },
                function (failed) {
                    throw failed;
                }).finally(function () {
                });
            return promise;

        }

        vm.clearPasswordForm = function () {
            vm.passwordInfo.OldPassword = null;
            vm.passwordInfo.NewPassword = null;
            vm.passwordInfo.ConfirmPassword = null;
            vm.showUnsuccessfulPasswordChange = false;
            vm.verificationEmailError = false;
            vm.passwordChangeMessage = "";
            vm.verificationEmailErrorMessage = "";
            vm.showPasswordExpired = false;
            vm.password_form.$setPristine();
            vm.isPasswordValid = false;
            vm.displayVerifyYourIdentity = false;
        };

        vm.validateForm = function () {
            $timeout(function () {
                vm.errors = wbxListErrorsService.getErrorListForBanner(vm.password_form);
            }, 0);
        };

        $scope.$watch('vm.password_form.$pristine', function (n, o) {
            if (n != o && !n) {
                vm.showPasswordUpdated = false;
                vm.showUnsuccessfulPasswordChange = false;
                vm.verificationEmailError = false;
                vm.passwordChangeMessage = "";
                vm.verificationEmailErrorMessage = "";
            }
        });
        function getMaskedEmail() {
            multifactorService.getUserData().then(function (res) {
                vm.maskedData = res.data;
            });

        }

        vm.goBack = function () {
            vm.displayVerifyYourIdentity = false;
            vm.showHeader();       
        }

        vm.showHeader = function (){
            if(vm.isForgotPassword || vm.resetPasswordBtn){
                vm.clickBackButton();
            } 
        }

        vm.hideHeader = function (){
            if(vm.isForgotPassword || vm.resetPasswordBtn){
                vm.hideParentHeader();
            } 
        }
    }
})();

;
(function () {
    "use strict";
    app.component('wbxListErrors',
        {
            templateUrl: '/Templates/ListErrors',
            controller: wbxListErrorsController,
            controllerAs: 'vm',
            bindings: {
                errorList: "="
            }
        });

    wbxListErrorsController.$inject = ['wbxValidationService'];

    function wbxListErrorsController(wbxValidationService) {
        var vm = this;

        vm.$onInit = onInit;
        vm.getErrorKey = getErrorKey;
        vm.getErrorParams = getErrorParams;
        vm.initErrorMessages = initErrorMessages;

        function onInit() {
            
            vm.knownErrors = {};
        }


        function initErrorMessages(error) {
            vm.knownErrors[error.wbxName] = wbxValidationService.get(error.overrideValidationsText)
        }

        function getErrorKey(name, errorList) {
            return _.find(errorList, function (item) {
                return item.Name == name
            }).Text

        }
        function getErrorParams(name, errorList) {
            return _.find(errorList, function (item) {
                return item.Name == name
            }).Params

        }
    }

})();
;
(function () {
    "use strict";
    app.component('wbxOperationHoursReadOnlyWrapper',
        {
            templateUrl: '/Templates/OperationHoursWrapper',
            controller: OperationHoursReadOnlyWrapperCtrl,
            controllerAs: 'vm',
            bindings: {
                operationHours: '=?'
            }
        });

    OperationHoursReadOnlyWrapperCtrl.$inject = [];

    function OperationHoursReadOnlyWrapperCtrl() {
        var vm = this;
        vm.isReadOnly = true;
        vm.days = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'];
        vm.dayOrder = {
            'Monday': 1,
            'Tuesday': 2,
            'Wednesday': 3,
            'Thursday': 4,
            'Friday': 5,
            'Saturday': 6,
            'Sunday': 7
        }

        vm.$onInit = function () {
            vm.setDefaultOperationHours();
            vm.sortDays();
        }

        vm.setDefaultOperationHours = function () {
            if (vm.operationHours === null || vm.operationHours === undefined || vm.operationHours === '' || !angular.isArray(vm.operationHours) || vm.operationHours.length == 0) {
                //If nothing is provided
                vm.operationHours = [];
                for (var i = 0; i < 7; i++) {
                    vm.operationHours.push({
                        DAY: vm.days[i],
                        HR_START1: null,
                        HR_END1: null,
                        HR_START2: null,
                        HR_END2: null
                    });
                }
            }
            else {
                //Fill in the missing time with default value
                vm.days.map(function (day) {
                    var exists = vm.operationHours.some(function (hours) {
                        return hours.DAY === day;
                    });

                    if (!exists) {
                        vm.operationHours.push({
                            DAY: day,
                            HR_START1: null,
                            HR_END1: null,
                            HR_START2: null,
                            HR_END2: null,
                            IS_CLOSED: true
                        });
                    }
                });
            }
        }

        vm.sortDays = function () {
            vm.operationHours.sort(function (a, b) {
                return vm.dayOrder[a.DAY] - vm.dayOrder[b.DAY];
            });
        }

        vm.officeClosedCheckboxOnChange = function () {
            for (var i = 0; i < 7; i++) {
                if (vm.operationHours[i].IS_CLOSED) {
                    vm.operationHours[i].HR_START1 = null;
                    vm.operationHours[i].HR_END1 = null;
                    vm.operationHours[i].HR_START2 = null;
                    vm.operationHours[i].HR_END2 = null;
                }
            }
        }
    }
})();;
(function () {
    "use strict";
    app.component('wbxOperationHoursWrapper',
        {
            templateUrl: '/Templates/OperationHoursWrapper',
            require: {
                form: '^^form'
            },
            controller: OperationHoursWrapperCtrl,
            controllerAs: 'vm',
            bindings: {
                operationHours: '=?'
            }
        });

    OperationHoursWrapperCtrl.$inject = [];

    function OperationHoursWrapperCtrl() {
        var vm = this;
        vm.isReadOnly = false;
        vm.days = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'];
        vm.dayOrder = {
            'Monday': 1,
            'Tuesday': 2,
            'Wednesday': 3,
            'Thursday': 4,
            'Friday': 5,
            'Saturday': 6,
            'Sunday': 7
        }

        vm.$onInit = function () {
            vm.setDefaultOperationHours();
            vm.sortDays();
        }

        vm.setDefaultOperationHours = function () {
            if (vm.operationHours === null || vm.operationHours === undefined || vm.operationHours === '' || !angular.isArray(vm.operationHours) || vm.operationHours.length == 0) {
                //If nothing is provided
                vm.operationHours = [];
                for (var i = 0; i < 7; i++) {
                    vm.operationHours.push({
                        DAY: vm.days[i],
                        HR_START1: null,
                        HR_END1: null,
                        HR_START2: null,
                        HR_END2: null
                    });
                }
            }
            else {
                //Fill in the missing time with default value
                vm.days.map(function (day) {
                    var exists = vm.operationHours.some(function (hours) {
                        return hours.DAY === day;
                    });

                    if (!exists) {
                        vm.operationHours.push({
                            DAY: day,
                            HR_START1: null,
                            HR_END1: null,
                            HR_START2: null,
                            HR_END2: null,
                            IS_CLOSED: true
                        });
                    }
                });
            }
        }

        vm.sortDays = function () {
            vm.operationHours.sort(function (a, b) {
                return vm.dayOrder[a.DAY] - vm.dayOrder[b.DAY];
            });
        }

        vm.officeClosedCheckboxOnChange = function () {
            for (var i = 0; i < 7; i++) {
                if (vm.operationHours[i].IS_CLOSED) {
                    vm.operationHours[i].HR_START1 = null;
                    vm.operationHours[i].HR_END1 = null;
                    vm.operationHours[i].HR_START2 = null;
                    vm.operationHours[i].HR_END2 = null;
                }
            }
        }
    }
})();;
(function () {
    'use strict';
    app.component('wbxPasswordAboutToExpire',
    {
        templateUrl: '/Templates/PasswordAboutToExpire',
        controller: PasswordAboutToExpireCtrl,
        controllerAs: 'vm'
    });

    PasswordAboutToExpireCtrl.$inject = ['$window', '$http'];

    function PasswordAboutToExpireCtrl($window, $http) {
        var vm = this;
        vm.$onInit = init;

        function init() {
            vm.getSessionInfo();
        }

        vm.routeToChangePassword = function() {
            $window.location.href = '/AccountManagement#/Password';
        }

        vm.getSessionInfo = function () {

                $http({
                    method: 'GET',
                    url: '/Account/GetSessionInfo'
                }).then(function successCallback(response) {
                    vm.populateSessionInfo(response.data);
                }, function errorCallback(response) {
                });
            }

        vm.populateSessionInfo = function (sessionInfo) {
            vm.showPasswordAboutToExpire = sessionInfo.IS_PASSWORD_ABOUT_TO_EXPIRE;
            vm.daysPasswordAboutToExpire = sessionInfo.DAYS_PASSWORD_ABOUT_TO_EXPIRE;
        }
    }
})();

;
;
app.component('wbxStepper', {
    templateUrl: '/Templates/wbxStepper',
    controllerAs: 'vm',
    controller: stepperCtrl,
    transclude: true,
    bindings: {
        steps: "@",
        stepNames: "=",
        fixed: "@",
        showButtonNavigation: "@"
    }
});

app.filter('range', function () {
    return function (input, total) {
        total = parseInt(total);
        for (var i = 0; i < total; i++)
            input.push(i);
        return input;
    };
});

stepperCtrl.$inject = ['$scope', '$timeout', '$rootScope', '$window'];

function stepperCtrl($scope, $timeout, $rootScope, $window) {
    var vm = this;
    vm.StateManager = [];
    vm.currentStep = 0;


    vm.$onInit = function () {
        vm.showNavigation = vm.setShowNavigation();
        vm.fixed = vm.fixed || false;
        vm.initStateManager();
        vm.updateDisplayMode();
    }

    vm.setShowNavigation = function () {
        if (vm.showButtonNavigation) {
            return (vm.showButtonNavigation.toLowerCase() === 'true');
        }
        return true;
    }

    vm.initStateManager = function () {

        for (var i = 0; i < vm.steps; i++) {
        
            if (i === 0) {
                vm.StateManager.push({
                    step: i,
                    disabled: false,
                    active: true,
                    completed: false
                });
            }
            else {
                vm.StateManager.push({
                    step: i,
                    disabled: true,
                    active: false,
                    completed: false
                });
            }
        }       
    }

    vm.confirmStep = function (step) {

        if (step === vm.StateManager.length) {
            return;
        }

        if (step > 0) {
            vm.markBeforeStepsAsCompleted(step);
        }

        vm.setCurrentStepStatus(step);
    }


    vm.reConfirmStep = function () {

        var stepNum = vm.getActiveStatusStep();
        vm.markBeforeStepsAsCompleted(stepNum);
        vm.setCurrentStepStatus(stepNum);

    }

    vm.selectStep = function (step, event) {

        if (vm.currentStep < step && !vm.StateManager[step].completed) {
            event.stopPropagation();
            return;
        }

        var tabContent = vm.getTabContentElements();
        vm.removeActiveClassFromTabContentElements(tabContent);
        vm.addActiveClassToCurrentStepElement(tabContent, step);
      
        vm.StateManager[vm.currentStep].disabled = false;
        vm.StateManager[vm.currentStep].completed = true;
        vm.StateManager[vm.currentStep].active = false;

        vm.setCurrentStepStatus(step);

        $scope.$emit("stepperSelectedStep", ++step);
    }

    vm.getTabContentElements = function () {
        return $('.tab-content').children();
    }

    vm.removeActiveClassFromTabContentElements = function(tabContent) {
        tabContent.map(function (element) {
            $('#' + tabContent[element].id).removeClass('active');
        });
    }

    vm.addActiveClassToCurrentStepElement = function(tabContent, step) {
        $("#" + tabContent[step].id).addClass('active');
    }

    vm.setCurrentStepStatus = function (step) {
        vm.StateManager[step].disabled = false;
        vm.StateManager[step].completed = false;
        vm.StateManager[step].active = true;

        vm.currentStep = step;
    }

    vm.markBeforeStepsAsCompleted = function (step) {

        vm.StateManager.map(function (stepState) {

            if (stepState.step <= step) {
                stepState.disabled = false;
                stepState.completed = true;
                stepState.active = false;
            }

            if (stepState.step > step) {
                stepState.disabled = true;
                stepState.active = false;
                stepState.completed = false;
            }
        });
    }

    vm.getActiveStatusStep = function () {
        var stepNum = 0;
        for (var i = 0; i < vm.StateManager.length; i++) {

            if (vm.StateManager[i].active) {
                stepNum = vm.StateManager[i].step;
                break;
            }
        }
        return stepNum;
    }



    vm.next = function (event) {
        //prevents from going to the next step
        if (vm.currentStep !== vm.StateManager.length - 1) {

            if (vm.StateManager[vm.currentStep + 1].disabled) {
                event.stopPropagation();
                return;
            }
        }

        var newStep = vm.currentStep + 1;
        vm.selectStep(newStep);
    }

    vm.completeStepClicked = false;
    vm.nextAndConfirm = function () {

        if (!vm.completeStepClicked) {
            vm.completeStepClicked = true;
            var tabContent = vm.getTabContentElements();

            vm.removeActiveClassFromTabContentElements(tabContent);

            var newStep = vm.currentStep + 1;
            vm.confirmStep(newStep);
            vm.addActiveClassToCurrentStepElement(tabContent, vm.currentStep);

            $timeout(function () {
                vm.completeStepClicked = false;
            }, 500);
        }
    }


    vm.back = function () {
        var newStep = vm.currentStep - 1;
        vm.selectStep(newStep);
    }

    vm.finish = function () {
        vm.StateManager[vm.currentStep].disabled = false;
        vm.StateManager[vm.currentStep].completed = true;
        vm.StateManager[vm.currentStep].active = false;

        $scope.$emit('stepperStepsCompleted');
    }

    $timeout(function () {
        vm.setActiveStep();
        vm.confirmStep(vm.currentStep);
    });

    vm.setActiveStep = function () {
        var tabContent = $('.tab-content').children();

        tabContent.map(function (element) {
            var hasClass = $('#' + tabContent[element].id).hasClass('active');

            if (hasClass) {
                vm.currentStep = element;
            }
        });

    }

    vm.showNextButton = function () {
        vm.stepConfirmed = true;
        vm.nextAndConfirm();
    }

    //////////
    //EVENTS//
    //////////
    $scope.$on('stepperCompletedStep', function (event, data) {
        vm.nextAndConfirm();
    });

    $scope.$on('stepperNextStep', function (event) {
        vm.next(event);
    });

    $scope.$on('stepperBackStep', function (event) {
        vm.back();
    });


    $scope.$on('stepperSelectNewStep', function (event, step) {
        vm.selectStep(--step, event);
    });

    $scope.$on('stepperReConfirmCurrentStep', function (event) {
        vm.reConfirmStep();
    });


    $scope.$on('stepperFinishSteps', function (event) {
        vm.finish();
    });

    $scope.$on('stepperResetWizard', function (event) {
        vm.currentStep = 0;
        vm.confirmStep(0);
        vm.stepConfirmed = false;
    });

    angular.element($window).bind('resize', function () {
        vm.updateDisplayMode();
    });



    vm.updateDisplayMode = function () {
        var myNav = $(".nav-tabs");
        var myContent = $("tab-content");
        var maxStepsWithVerticalNavOnMobile = 5;
        var maxStepsWithVertical = 9;
        var mobilePixelSize = 667;


        if (($window.innerWidth < mobilePixelSize && vm.steps > maxStepsWithVerticalNavOnMobile) || vm.steps > maxStepsWithVertical) {
            if (!myNav.hasClass('nav-stacked')) {
                myNav.addClass('nav-stacked');
            }

            if (myNav.hasClass('stickyHeading')) {
                myNav.removeClass('stickyHeading');
            }

        } else {
            if (myNav.hasClass('nav-stacked')) {
                myNav.removeClass('nav-stacked');
            }
            if (!myNav.hasClass('stickyHeading')) {
                myNav.addClass('stickyHeading');
            }
        }
    }
};
(function() {
    "use strict";
    app.component('wbxValidationAsterisk',
    {
        templateUrl: '/Templates/ValidationAsterisk',
        require: {
            form: '^^form'
        },
        controller: ValidationAsteriskCtrl,
        controllerAs: 'vm',
        bindings: {
            controlName: '@',
            isRequired: '<'
        }
    });

    ValidationAsteriskCtrl.$inject = [];

    function ValidationAsteriskCtrl() {
        var vm = this;
    }
})();;
(function () {
    "use strict";
    app.component('wbxValidationCaret',
    {
        templateUrl: '/Templates/ValidationCaret',
        require: {
            form: '^^form'
        },
        controller: ValidationCaretCtrl,
        controllerAs: 'vm',
        bindings: {
            controlName: '@',
            isRequired: '<',
            overrideErrorList: '@'
        }
    });

    ValidationCaretCtrl.$inject = ['$timeout', '$compile', '$scope', 'wbxValidationService'];

    function ValidationCaretCtrl($timeout, $compile, $scope, wbxValidationService) {
        var vm = this;
        var expressions = [];
        vm.errorCount = 0;

        vm.$onInit = function () {
            vm.errorList = wbxValidationService.get(vm.overrideErrorList);

            var errorMessages = "<ul class=\"list-unstyled ng-scope\">";
            var paramString = "";
            angular.forEach(vm.errorList, function (error) {
                if (error.Params) {
                    paramString = " translate-values=\"" + angular.toJson(error.Params).replace(/"/g, "") + "\"";
                }
                errorMessages += "<li ng-if=\"vm.form." + vm.controlName + ".$error." + error.Name + "\" translate=\"" + error.Text + "\"" + paramString + "></li>";
            });

            errorMessages += "<li ng-if=\"vm.isRequired && !vm.form." + vm.controlName + ".$invalid\" translate=\"Inline_Validation_Required\"></li>";
            errorMessages += "</ul>";

            var compiledErrorMessages = $compile(errorMessages)($scope);
            $timeout(function () {
                $('#' + vm.controlName + "Caret").tooltip({
                    placement: 'right',
                    html: true,
                    title: compiledErrorMessages,
                    container: 'body'
                });
            });

            vm.errorCount = expressions.length;
        };
    }
})();;
(function () {
    "use strict";
    app.component('wbxValidationText',
        {
            templateUrl: '/Templates/ValidationText',
            require: {
                form: '^^form'
            },
            controller: ValidationTextCtrl,
            controllerAs: 'vm',
            bindings: {
                controlName: '@',
                overrideErrorList: '@' //Changed from < to @ so that we'll get the compiled string. (value instead of {{variable}})
            }
        });

    ValidationTextCtrl.$inject = ['wbxValidationService'];

    function ValidationTextCtrl(wbxValidationService) {
        var vm = this;
        vm.controlName = vm.controlName.replace(/\s/g, ''); //Remove empty spaces
        vm.controlNameArray = vm.controlName.split(','); //Parse string into array

        vm.$onInit = function () {
            vm.errorList = wbxValidationService.get(vm.overrideErrorList);
        };
    }

})();;
(function () {
    'use strict';
    app.service('wbxChangePasswordService', wbxChangePasswordService);
    wbxChangePasswordService.$inject = ['API', '$window', '$q'];
    function wbxChangePasswordService(API, $window, $q) {
        var vm = this;

        //Account Managemnt PasswordTab
        vm.changePasswordWithCurrentPassword = function (passwordChangeInfo) {
            var deferred = $q.defer();
            API.put('/AccountManagement/ChangePassword',
                {
                    CODE: passwordChangeInfo.CODE,
                    METHOD: passwordChangeInfo.METHOD,
                    USER_NAME: passwordChangeInfo.USER_NAME,
                    CURRENT_PASSWORD: passwordChangeInfo.OldPassword,
                    NEW_PASSWORD: passwordChangeInfo.NewPassword,
                    CONFIRM_PASSWORD: passwordChangeInfo.ConfirmPassword
                })
                .then(
                    function (success) {
                        deferred.resolve(success);
                    },
                    function (failed) {
                        deferred.reject(failed);
                    });

            return deferred.promise;
        }

        // Reset password (password expired)
        vm.changeExpiredPasswordWithCurrentPassword = function (passwordChangeInfo) {
            var deferred = $q.defer();
            API.put('/ResetPassword/ResetPassword',
                {
                    CODE: passwordChangeInfo.CODE,
                    METHOD: passwordChangeInfo.METHOD,
                    USER_NAME: passwordChangeInfo.USER_NAME,
                    CURRENT_PASSWORD: passwordChangeInfo.OldPassword,
                    NEW_PASSWORD: passwordChangeInfo.NewPassword,
                    CONFIRM_PASSWORD: passwordChangeInfo.ConfirmPassword
                })
                .then(
                    function (success) {
                        deferred.resolve(success);
                    },
                    function (failed) {
                        deferred.reject(failed);
                    });

            return deferred.promise;
        }

        //ChangePassword Page (Forgot password)
        vm.changePassword = function (PasswordInformation) {
            var deferred = $q.defer();
            API.put('/Account/ChangePassword',
            {
                CODE: PasswordInformation.CODE,
                METHOD: PasswordInformation.METHOD,
                USER_NAME: PasswordInformation.USER_NAME,
                NEW_PASSWORD: PasswordInformation.NewPassword,
                CONFIRM_PASSWORD: PasswordInformation.ConfirmPassword,
                RESETPASS_VID: PasswordInformation.RESETPASS_VID
            }).then(function (success) {
                deferred.resolve(success);
            },
            function (failed) {
                deferred.reject(failed);
            });
            return deferred.promise;
        }

        vm.sendCodeByUserName = function (PasswordInformation) {
            return API.put('/Account/SendCodeByUserName',
            {
                USER_NAME: PasswordInformation.USER_NAME,
            });
        }

        vm.validateResetPasswordInfo = function (passwordInformation) {
            return API.post('/Account/ValidateResetPasswordInfo',
            {
                CODE: passwordInformation.CODE,
                METHOD: passwordInformation.METHOD,
                USER_NAME: passwordInformation.USER_NAME,
                NEW_PASSWORD: passwordInformation.NewPassword,
                CONFIRM_PASSWORD: passwordInformation.ConfirmPassword,
                RESETPASS_VID: passwordInformation.RESETPASS_VID
            });
        }

        vm.validateChangePasswordInfo = function (passwordChangeInfo) {
            return API.post('/AccountManagement/ValidateChangePasswordInfo',
            {
            CODE: passwordChangeInfo.CODE,
            METHOD: passwordChangeInfo.METHOD,
            USER_NAME: passwordChangeInfo.USER_NAME,
            CURRENT_PASSWORD: passwordChangeInfo.OldPassword,
            NEW_PASSWORD: passwordChangeInfo.NewPassword,
            CONFIRM_PASSWORD: passwordChangeInfo.ConfirmPassword
            });
        }

        vm.validateExpiredPasswordInfo = function (passwordChangeInfo) {
            return API.post('/ResetPassword/ValidateExpiredPasswordInfo',
            {
            CODE: passwordChangeInfo.CODE,
            METHOD: passwordChangeInfo.METHOD,
            USER_NAME: passwordChangeInfo.USER_NAME,
            CURRENT_PASSWORD: passwordChangeInfo.OldPassword,
            NEW_PASSWORD: passwordChangeInfo.NewPassword,
            CONFIRM_PASSWORD: passwordChangeInfo.ConfirmPassword
            });
        }
    }
})();

;
(function () {
    "use strict";
    app.service('wbxListErrorsService', wbxListErrorsService);
    wbxListErrorsService.$inject = []
    function wbxListErrorsService() {
        return {
            getErrorListForBanner: getErrorListForBanner,
            updateFormWithLabels: updateFormWithLabels
        }

        function getErrorListForBanner(form) {
            if(form.controlsList === undefined) return [];
            var errors = [];
            form.controlsList.forEach(function (item) {
                if(form[item] === undefined) return;
                const inputErrorList = Object.keys(form[item].$error);
                if (inputErrorList.length === 0)
                    return;
                errors.push({wbxName : item,  labelKey: form[item].wbxLabelKey, inputErrors: inputErrorList, overrideValidationsText : form[item].wbxOverrideValidations });
            });
            return errors;
        }
        function updateFormWithLabels(formControl, labelKey) {
            if (formControl == null) return;
            formControl.wbxLabelKey = labelKey;

        }
    }

})();;
;
(function () {
    'use strict';
    app.service('WbxStepperService', WbxStepperService);
    WbxStepperService.$inject = ['$rootScope'];
    function WbxStepperService($rootScope) {

        return {
            CompleteStep: CompleteStep,
            NextStep: NextStep,
            BackStep: BackStep,
            SelectNewStep: SelectNewStep,
            ReconfirmCurrentStep: ReconfirmCurrentStep,
            FinishSteps: FinishSteps,
            ResetStepper: ResetStepper
        }

        function CompleteStep() {
            $rootScope.$broadcast('stepperCompletedStep');
        }

        function NextStep() {
            $rootScope.$broadcast('stepperNextStep');
        }

        function BackStep() {
            $rootScope.$broadcast('stepperBackStep');
        }

        function SelectNewStep(step) {
            $rootScope.$broadcast('stepperSelectNewStep', step);
        }

        function ReconfirmCurrentStep() {
            $rootScope.$broadcast('stepperReConfirmCurrentStep');
        }

        function FinishSteps() {
            $rootScope.$broadcast('stepperFinishSteps');
        }

        function ResetStepper() {
            $rootScope.$broadcast('stepperResetWizard');
        }
        
    }
})();

;
(function () {
    "use strict";
    app.component('wbxDynamicFormFieldReadOnly',
        {
            templateUrl: '/WrapperTemplates/DynamicFormField',
            controller: DynamicFormFieldCtrl,
            controllerAs: 'vm',
            bindings: {
                formId: '@',
                labelWidth: '=',
                isReadOnlyShowingDash: '=',
                fieldList: '=',
                isDangerColor: '=',
                isSuccessColor: '=',
                isWarningColor: '=',
                isInfoColor: '='
            }
        });

    DynamicFormFieldCtrl.$inject = ['$scope'];

    function DynamicFormFieldCtrl($scope) {
        var vm = this;
        vm.SubSectionList = [];
        vm.isReadOnly = true;

        vm.setFormLevelInfo = function (field) {
            field.LabelWidth = vm.labelWidth;
        }

        $scope.$watchCollection('vm.fieldList', function (n, o) {
            if (n !== null) {
                var placeHolderSubGroupList = [];
                vm.SubSectionList = [];

                if (vm.fieldList != null && vm.fieldList[0] != null && !vm.fieldList[0].hasOwnProperty('DynamicFieldList')) {
                    //Check the first item to see if it has DynamicFieldList property. If it doesn't have it, it means it's a flat structure of fields.
                    //To fit the view, all the fields would be put into a subsection of one with null subsection label.

                    var placeHolderSubSection = {
                        Label: null,
                        DynamicFieldList: n
                    };

                    placeHolderSubGroupList.push(placeHolderSubSection);
                }
                else {
                    placeHolderSubGroupList = n;
                }

                angular.forEach(placeHolderSubGroupList, function (subGroup) {
                    var subSection = {
                        Label: subGroup.Label,
                        DynamicFieldList: []
                    };

                    angular.forEach(subGroup.DynamicFieldList, function (field) {
                        vm.setFormLevelInfo(field);

                        subSection.DynamicFieldList.push(field);
                    });

                    vm.SubSectionList.push(subSection);
                });
            }
        });
    }
})();;
(function () {
    "use strict";
    app.component('wbxDynamicFormField',
        {
            templateUrl: '/WrapperTemplates/DynamicFormField',
            require: {
                form: '^^form'
            },
            controller: DynamicFormFieldCtrl,
            controllerAs: 'vm',
            bindings: {
                formId: '@',
                labelWidth: '=',
                fieldList: '=',
                isSideLabel: '=',
                isOldValidation: '=',
                isReadOnlyShowingDash: '=',
                fieldTypeInfo: '='
            }
        });

    DynamicFormFieldCtrl.$inject = ['$scope'];

    function DynamicFormFieldCtrl($scope) {
        var vm = this;
        vm.SubSectionList = [];
        vm.isReadOnly = false;

        vm.setFormLevelInfo = function (field) {
            field.LabelWidth = vm.labelWidth;
        }

        vm.setFieldTypeInfo = function (field) {
            if (vm.fieldTypeInfo.IsAlphaNumeric) {
                field.Type = 'text';
                field.IsRequired = false;
                field.IsDisabled = false;
                field.HasSSNMask = false;

                field.MaxLength = vm.fieldTypeInfo.FieldMaxLength;
                field.InputWidth = vm.fieldTypeInfo.IsMaxWidth ? null : 4; //Either extra large or maximum            
            }
            else {
                field.Type = 'text';
                field.IsRequired = false;
                field.IsDisabled = false;
                field.HasSSNMask = false;
            }
        }

        $scope.$watchCollection('[vm.fieldTypeInfo, vm.fieldList]', function (n, o) {
            if (n !== null && n[0] !== null && n[1] != null) {
                var placeHolderSubGroupList = [];
                vm.SubSectionList = [];

                if (vm.fieldList != null && vm.fieldList[0] != null && !vm.fieldList[0].hasOwnProperty('DynamicFieldList')) {
                    //Check the first item to see if it has DynamicFieldList property. If it doesn't have it, it means it's a flat structure of fields.
                    //To fit the view, all the fields would be put into a subsection of one with null subsection label.

                    var placeHolderSubSection = {
                        Label: null,
                        DynamicFieldList: vm.fieldList
                    };

                    placeHolderSubGroupList.push(placeHolderSubSection);
                }
                else {
                    placeHolderSubGroupList = vm.fieldList;
                }

                angular.forEach(placeHolderSubGroupList, function (subGroup) {
                    var subSection = {
                        Label: subGroup.Label,
                        DynamicFieldList: []
                    };

                    angular.forEach(subGroup.DynamicFieldList, function (field) {
                        vm.setFormLevelInfo(field);
                        vm.setFieldTypeInfo(field);

                        subSection.DynamicFieldList.push(field);
                    });

                    vm.SubSectionList.push(subSection);
                });
            }
        });
    }
})();;
(function () {
    'use strict';
    app.service("wbxValidationService", wbxValidationService);

    wbxValidationService.$inject = [];

    function wbxValidationService() {
        var vm = this;

        var errorList = [
            {
                Name: 'required',
                Text: 'Inline_Validation_Required'
            },
            {
                Name: 'incomplete',
                Text: 'Inline_Validation_Incomplete'
            },
            {
                Name: 'incompleteZip',
                Text: 'Inline_Validation_Incomplete_Zip'
            },
            {
                Name: 'email',
                Text: 'Inline_Validation_Invalid_Email_Format'
            },
            {
                Name: 'PasswordNotValid',
                Text: 'Inline_Validation_Failed_Password_Criteria'
            },
            {
                Name: 'notMatched',
                Text: 'Inline_Validation_Not_Matched'
            },
            {
                Name: 'isBefore',
                Text: 'Inline_Validation_Is_Before_Date'
            },
            {
                Name: 'isBeforeTime',
                Text: 'Inline_Validation_Is_Before_Time'
            },
            {
                Name: 'isAfter',
                Text: 'Inline_Validation_Is_After_Date'
            },
            {
                Name: 'isAfterTime',
                Text: 'Inline_Validation_Is_After_Time'
            },
            {
                Name: 'isNotFuture',
                Text: 'Inline_Validation_Not_Future_Date'
            },
            {
                Name: 'noValue',
                Text: 'Inline_Validation_No_Value'
            },
            {
                Name: 'wbxDateRange',
                Text: 'Inline_Validation_Outside_Date_Range'
            },
            {
                Name: 'npi',
                Text: 'Inline_Validation_NPI'
            },
            {
                Name: 'routingNumber',
                Text: 'Inline_Validation_Routing_Number'
            },
            {
                Name: 'ADA_AccountNumber',
                Text: 'Inline_Validation_ADA_Account_Number'
            },
            {
                Name: 'isBeforeInt',
                Text: 'Inline_Validation_Is_Before_Int'
            },
            {
                Name: 'isAfterInt',
                Text: 'Inline_Validation_Is_After_Int'
            },
            {
                Name: 'minValue',
                Text: 'Inline_Validation_Min_Value'
            },
            {
                Name: 'maxValue',
                Text: 'Inline_Validation_Max_Value'
            },
            {
                Name: 'minAge',
                Text: 'Inline_Validation_Too_Young'
            },
            {
                Name: 'minCharactersVariableLength',
                Text: 'Inline_Validation_Min_Characters'
            },
            {
                Name: 'isFutureExpDate',
                Text: 'Inline_Validation_Is_Future_Exp_Date'
            },
            {
                Name: 'routingNumbersMatch',
                Text: 'Inline_Validation_Routing_Numbers_Match'
            },
            {
                Name: 'routingNumberLength',
                Text: 'Inline_Validation_Routing_Number_Length'
            },
            {
                Name: 'accountNumbersMatch',
                Text: 'Inline_Validation_Account_Numbers_Match'
            }
        ];

        vm.get = function (overrideErrorList) {
            //This is so that the original text isn't overriden with the latest override.
            var newErrorList = angular.copy(errorList);

            //This part is necessary to convert from string to json
            if (overrideErrorList != null && overrideErrorList != "") {
                var overrideErrorListJson = null;
                var overrideErrorListWithDoubleQuotes = overrideErrorList.replace(/'/g, "\"");

                try {
                    //Replace ' with " and then parse it to json
                    overrideErrorListJson = JSON.parse(overrideErrorListWithDoubleQuotes);
                } catch (e) {
                    console.error(overrideErrorListWithDoubleQuotes);
                    overrideErrorListJson = null;
                }

                angular.forEach(overrideErrorListJson, function (overrideText, overrideName) {
                    if (overrideText) {
                        var trimmedText;
                        var overrideParams;
                        if(overrideText.match(/(\{\{(.*?)\}\})/gm) != null){
                            trimmedText = /(^[^\s]+)+(.\{\{.+)/gm.exec(overrideText)[1]
                            overrideParams = JSON.parse(overrideText.match(/(\{\{(.*?)\}\})/gm)[0].replace("{{","{").replace("}}","}").replaceAll("\\\"",'"'))
                        } else if (overrideText.indexOf("((") != -1) {
                            //If double parenthesis are detected, this means we need to pass parameters into the translation
                            trimmedText = overrideText.substring(0, overrideText.indexOf("((")).trim();
                            var paramString = overrideText.substring(overrideText.indexOf("((") + 2, overrideText.indexOf("))")).trim();
                            var paramName = paramString.substring(0, paramString.indexOf(":")).trim();
                            var paramValue = paramString.substring(paramString.indexOf(":") + 1, paramString.length).trim();
                            overrideParams = {};
                            overrideParams[paramName] = paramValue;
                        } else {
                            trimmedText = overrideText;
                            overrideParams = null;
                        }

                        var newError = _.findWhere(newErrorList, { Name: overrideName });

                        //If override text isn't provided (In the case of just wanting to replace (interpolate) the dynamic text
                        if (trimmedText == null || trimmedText == "") {
                            trimmedText = newError.Text;
                        }

                        if (!newError) {
                            //If not found in the default list, create a new record
                            newError = {
                                Name: overrideName,
                                Text: trimmedText,
                                Params: overrideParams
                            };
                            newErrorList.push(newError);
                        } else {
                            //If found, just update the text and possibly add the params
                            newError.Text = trimmedText;
                            newError.Params = overrideParams;
                        }
                    }
                });
            }

            return newErrorList;
        }
    }
})();;
