/* Minification failed. Returning unminified contents.
(83,22-23): run-time error JS1014: Invalid character: `
(83,23-24): run-time error JS1195: Expected expression: /
(83,88-89): run-time error JS1014: Invalid character: `
(84,7-8): run-time error JS1014: Invalid character: `
(84,8-9): run-time error JS1195: Expected expression: &
(84,69-70): run-time error JS1014: Invalid character: `
(85,7-8): run-time error JS1014: Invalid character: `
(85,8-9): run-time error JS1195: Expected expression: &
(85,43-44): run-time error JS1014: Invalid character: `
(86,7-8): run-time error JS1014: Invalid character: `
(86,8-9): run-time error JS1195: Expected expression: &
(86,51-52): run-time error JS1014: Invalid character: `
(86,52-53): run-time error JS1195: Expected expression: ,
(88,4-5): run-time error JS1195: Expected expression: )
(90,22-23): run-time error JS1004: Expected ';': {
(102,2-3): run-time error JS1002: Syntax error: }
(104,57-58): run-time error JS1004: Expected ';': {
(196,9-10): run-time error JS1014: Invalid character: `
(196,11-12): run-time error JS1100: Expected ',': {
(196,53-54): run-time error JS1003: Expected ':': {
(196,72-73): run-time error JS1003: Expected ':': (
(196,91-92): run-time error JS5008: Illegal assignment: =
(196,124-125): run-time error JS1014: Invalid character: `
(196,125-126): run-time error JS1195: Expected expression: ,
(198,3-4): run-time error JS1002: Syntax error: }
(200,21-22): run-time error JS1004: Expected ';': {
(204,3-4): run-time error JS1195: Expected expression: )
(207,67-68): run-time error JS1004: Expected ';': {
(212,9-10): run-time error JS1014: Invalid character: `
(212,11-12): run-time error JS1100: Expected ',': {
(212,57-58): run-time error JS1003: Expected ':': {
(212,76-77): run-time error JS1003: Expected ':': (
(212,104-105): run-time error JS5008: Illegal assignment: =
(212,142-143): run-time error JS1014: Invalid character: `
(212,143-144): run-time error JS1195: Expected expression: ,
(213,11-12): run-time error JS1197: Too many errors. The file might not be a JavaScript file: :
(202,5-17): run-time error JS1018: 'return' statement outside of function: return error
(105,3,118,4): run-time error JS1018: 'return' statement outside of function: return $.ajax({
			cache: false,
			async: true,
			type: "GET",
			url: _baseUrl + "/validation?username=" + encodeURIComponent(userName) + "&programId=" + encodeURIComponent(programId),
			contentType: "application/json",
			headers: _tokenHeader
		}).then(
			null,
			function (error) {
				error.responseText = "Error validating username.";
				return error;
			}
		)
(100,3-48): run-time error JS1018: 'return' statement outside of function: return { isValid: true, promotion: response }
(97,4-60): run-time error JS1018: 'return' statement outside of function: return { isValid: false, errorCode: response.errorCode }
(91,4-90): run-time error JS1018: 'return' statement outside of function: return { isValid: false, message: "Promotion code cannot be validated at this time." }
 */
function PortalClient(tokenHeader, baseUrl, gatewayBaseUrl) {

	// Private Members
	const _tokenHeader = tokenHeader;
	const _baseUrl = baseUrl;
	const _v2BaseUrl = (baseUrl.endsWith('/1') ? baseUrl.substring(0, baseUrl.length - 2) : baseUrl) + '/2';

	const _gatewayBaseUrl = gatewayBaseUrl;

	// Public Methods
	this.getUserLeaderBoard = function () {
		return $.ajax({
			cache: false,
			async: true,
			type: "GET",
			url: _baseUrl + "/user/leaderBoard",
			contentType: "application/json",
			headers: _tokenHeader
		}).then(
			null,
			function (error) {
				error.responseText = "Error retrieving leaderboard.";
				return error;
			}
		);
	};

	this.getUserStatements = function (month, year) {
		return $.ajax({
			cache: false,
			async: true,
			type: "GET",
			url: _baseUrl + "/user/statements?month=" + month + "&year=" + year,
			contentType: "application/json",
			headers: _tokenHeader
		}).then(
			null,
			function (error) {
				error.responseText = "Error retrieving user statements.";
				return error;
			}
		);
	};

	this.getUserTrips = function (month, year) {
		return $.ajax({
			cache: false,
			async: true,
			type: "GET",
			url: _baseUrl + "/user/trips?month=" + month + "&year=" + year,
			contentType: "application/json",
			headers: _tokenHeader
		}).then(
			null,
			function (error) {
				error.responseText = "Error retrieving user trips.";
				return error;
			}
		);
	};

	this.getUserOpenFailedTransactions = function () {
		return $.ajax({
			cache: false,
			async: true,
			type: "GET",
			url: _baseUrl + "/user/openfailedtransactions",
			headers: _tokenHeader
		}).then(
			null,
			function (error) {
				error.responseText = "Error getting user open failed transactions.";
				return error;
			}
		);
	};

	this.validatePromotionCodeSync = function (programId, subscriptionTypeId, promotionCode, email) {
		var responseText = $.ajax({
			cache: false,
			async: false,
			type: "GET",
			url: _v2BaseUrl + `/promotioncode?promotionCode=${encodeURIComponent(promotionCode)}`
				+ `&subscriptionTypeId=${encodeURIComponent(subscriptionTypeId)}`
				+ `&email=${encodeURIComponent(email)}`
				+ `&programId=${encodeURIComponent(programId)}`,
			headers: _tokenHeader
		}).responseText;

		if (!responseText) {
			return { isValid: false, message: "Promotion code cannot be validated at this time." };
		}

		var response = JSON.parse(responseText);

		if (response.errorCode) {
			return { isValid: false, errorCode: response.errorCode };
		}

		return { isValid: true, promotion: response };

	};

	this.validateUserName = function (userName, programId) {
		return $.ajax({
			cache: false,
			async: true,
			type: "GET",
			url: _baseUrl + "/validation?username=" + encodeURIComponent(userName) + "&programId=" + encodeURIComponent(programId),
			contentType: "application/json",
			headers: _tokenHeader
		}).then(
			null,
			function (error) {
				error.responseText = "Error validating username.";
				return error;
			}
		);
	};

	this.requestPasswordReset = function (usernameOrEmail, programId) {
		return $.ajax({
			cache: false,
			async: true,
			type: "POST",
			url: _baseUrl + "/user/" + usernameOrEmail + "/resetpasswordtoken?programId="+programId,
			contentType: "application/json",
			headers: _tokenHeader
		}).then(
			null,
			function (error) {
				error.responseText = "Error requesting password reset.";
				return error;
			}
		);
	};

	this.validatePasswordToken = function (token, tenant) {
		return $.ajax({
			cache: false,
			async: true,
			type: "GET",
			url: _gatewayBaseUrl + "/" + tenant + "/user/resetpasswordtoken/" + token,
			contentType: "application/json",
			headers: _tokenHeader
		}).then(
			null,
			function (error) {
				error.responseText = "Error validating token.";
				return error;
			}
		);
	};

	this.resetPasswordWithToken = function (newPassword, token, tenant) {
		return $.ajax({
			cache: false,
			async: false,
			type: "POST",
			url: _gatewayBaseUrl + "/" + tenant + "/user/resetpasswordtoken/" + token,
			data: JSON.stringify({ "newPassword": newPassword }),
			contentType: "application/json",
			headers: _tokenHeader
		}).then(
			null,
			function (error) {
				error.responseText = "Error resetting password.";
				return error;
			}
		);
	};

	this.updateStripePaymentProfile = function (token) {
		return $.ajax({
			cache: false,
			async: true,
			type: "PUT",
			url: _baseUrl + "/stripe/paymentprofile",
			data: JSON.stringify({"tokenId": token}),
			contentType: "application/json",
			headers: _tokenHeader
		}).then(
			null,
			function (error) {
				error.responseText = "Error updating Stripe payment profile.";
				return error;
			}
		);
	};

	this.settleDelinquency = function (userId, programId) {
		return $.ajax({
			cache: false,
			async: true,
			type: "PUT",
			url: `${_baseUrl}/user/settledelinquency?userId=${encodeURIComponent(userId)}&programId=${encodeURIComponent(programId)}`,
			headers: _tokenHeader
		}).then(
			null,
			function (error) {
				error.responseText = "Error settling delinquency.";
				return error;
			}
		);
	};

	this.simpleRenew = function (subscriptionTypeId, purchaseSource) {
		return $.ajax({
			cache: false,
			async: true,
			type: "POST",
			url: `${_baseUrl}/renewal/simple?subscriptionTypeId=${encodeURIComponent(subscriptionTypeId)}&source=${encodeURIComponent(purchaseSource)}`,
			headers: _tokenHeader
		}).then(
			null,
			function (error) {
				error.responseText = "Error renewing subscription.";
				return error;
			}
		);
	};

	this.patchUser = function (patchUserModel) {
		return $.ajax({
			cache: false,
			async: true,
			type: "PATCH",
			url: `${_baseUrl}/user`,
			data: JSON.stringify(patchUserModel),
			contentType: "application/json",
			headers: _tokenHeader
		}).then(
			null,
			function (error) {
				error.responseText = "Error updating user";
				return error;
			}
		);
	}

	// Map Support
	this.getMapKiosks = function (programId) {
		let url = `${_baseUrl}/publicApi/kiosks`;
		if (programId) { url += `?programId=${programId}&refresh=true` };

		return $.ajax({
			cache: false,
			async: true,
			type: "GET",
			url: url,
			headers: _tokenHeader
		}).then(
			null,
			function (error) {
				error.responseText = "Error getting map kiosks.";
				return error;
			}
		);
	}

	this.getMapBikes = function (programId) {
		let url = `${_baseUrl}/publicApi/bikes`;
		if (programId) { url += `?programId=${programId}&refresh=true` };

		return $.ajax({
			cache: false,
			async: true,
			type: "GET",
			url: url,
			headers: _tokenHeader
		}).then(
			null,
			function (error) {
				error.responseText = "Error getting map bikes.";
				return error;
			}
		);
	}
}
;
function PrivatePortalClient(tokenType) {

	// Private Members
	const _self = this;
	this._clientManager = new PrivatePortalClientManager(tokenType);
	this._client = null;
    this._hasValidManagerAndClient = function () {
		if (_self._clientManager.getClient()) {
			_self._client = _self._clientManager.getClient();
        }
		return (_self._clientManager.isValid() && _self._client);
    };

    this.getClientPromise = function () {
		return $.when(!_self._hasValidManagerAndClient()).then(function (needClient) {
            if (needClient) {
				return $.ajax(_self._clientManager.buildClientManagerRequest(true)).then(function (result) {
					if (!result) {
						return { status: 204, responseText: "No bearer token available" };
					}

					_self._client = _self._clientManager.processClientManagerResponse(result);

					if (!_self._client) {
                        throw "An error occurred creating the internal portal client.";
                    }
                },
                function (error) {
                    return { status: 500, responseText: "An error occurred creating the internal portal client. This is most likely due to a missing or invalid token." };
                });
            } else {
                return $.Deferred().resolve(null).promise();
            }
        });
    };

    this.getClientSync = function () {
		var responseText = $.ajax(_self._clientManager.buildClientManagerRequest(false)).responseText;
        if (!responseText) {
            return false;
        }

        var response = JSON.parse(responseText);
        if (response.Message) {
            return false;
        }

		_self._client = _self._clientManager.processClientManagerResponse(response);
		if (!_self._client) {
            return false;
        }

        return true;
    };

	// Public Methods
	this.getSecurityQuestionByUser = function (username) {
		return _self.getClientPromise().then(function () {
			return _self._client.getSecurityQuestionByUser(username);
		});
	};


	this.getUserLeaderBoard = function () {
		return _self.getClientPromise().then(function () {
			return _self._client.getUserLeaderBoard();
		});
	};

	this.getUserStatements = function (month, year) {
		return _self.getClientPromise().then(function () {
			return _self._client.getUserStatements(month, year);
		});
	};

	this.getUserTrips = function (month, year) {
		return _self.getClientPromise().then(function () {
			return _self._client.getUserTrips(month, year);
		});
	};

    this.getUserOpenFailedTransactions = function () {
		return _self.getClientPromise().then(function () {
			return _self._client.getUserOpenFailedTransactions();
        });
    };

	this.resetPassword = function (username, answer) {
		return _self.getClientPromise().then(function () {
			return _self._client.resetPassword(username, answer);
		});
	};

	this.updateStripePaymentProfile = function (token) {
		return _self.getClientPromise().then(function () {
			return _self._client.updateStripePaymentProfile(token);
		});
	};

    this.settleDelinquency = function (userId, programId) {
		return _self.getClientPromise().then(function () {
			return _self._client.settleDelinquency(userId, programId);
        });
    };

    this.simpleRenew = function (subscriptionTypeId, purchaseSource) {
		return _self.getClientPromise().then(function () {
			return _self._client.simpleRenew(subscriptionTypeId, purchaseSource);
        });
    };

	this.validatePromotionCodeSync = function (programId, subscriptionTypeId, promotionCode, email) {
		if (!_self._hasValidManagerAndClient()) {

			if (_self.getClientSync()) {

				return _self._client.validatePromotionCodeSync(programId, subscriptionTypeId, promotionCode, email);
			}
			else {

				return { isValid: false, message: "Communication error retrieving url and token." };
			}

		} else {

			return _self._client.validatePromotionCodeSync(programId, subscriptionTypeId, promotionCode, email);
		}
	};

	this.validateUserName = function (userName, programId) {
		return _self.getClientPromise().then(function () {
			return _self._client.validateUserName(userName, programId);
			});
	};

	this.requestPasswordReset = function (usernameOrEmail, programId) {
		return _self.getClientPromise().then(function () {
			return _self._client.requestPasswordReset(usernameOrEmail, programId);
		});
	};

	this.validatePasswordToken = function (token, tenant) {
		return _self.getClientPromise().then(function () {
			return _self._client.validatePasswordToken(token, tenant);
		});
	};

	this.resetPasswordWithToken = function (newPassword, token, tenant) {
		return _self.getClientPromise().then(function () {
			return _self._client.resetPasswordWithToken(newPassword, token, tenant);
		});
	};

	this.patchUser = function (patchUserModel) {
		return _self.getClientPromise().then(function () {
			return _self._client.patchUser(patchUserModel);
		});
	};

	// Map Support
	this.getMapKiosks = function (programId) {
		return _self.getClientPromise().then(function () { return _self._client.getMapKiosks(programId); });
	}

	this.getMapBikes = function (programId) {
		return _self.getClientPromise().then(function () { return _self._client.getMapBikes(programId); });
	}

	return this;
}

var PortalClientTokenType = {
	None: 0,
	BearerClient: 2,
	BearerRopc: 3
};

function PrivatePortalClientManager(tokenType) {
	if (!tokenType) {
		throw 'Must provide token type';
	}

	// Private Members
	const _self = this;
	this._tokenType = tokenType;
	this._token = null;
	this._baseUrl = null;
	this._gatewayBaseUrl = null;

	// Public Members
	this.isValid = function () {
		return (_self._token && _self._baseUrl);
	}

	this.buildClientManagerRequest = function (isAsync) {
		var request = { cache: false, async: isAsync, type: "GET", url: null };

		switch (_self._tokenType) {
			case PortalClientTokenType.BearerClient:
				request.url = '/api/bearertoken/getclient';
				break;
			case PortalClientTokenType.BearerRopc:
				request.url = '/api/bearertoken/getropc';
				break;
		}

		return request;
	}

	this.processClientManagerResponse = function (result) {
		_self._baseUrl = result.Url;
		_self._gatewayBaseUrl = result.GatewayUrl;
		_self._token = result.BearerToken;

		return _self.getClient();
	}

	this.getTokenHeader = function () {
		switch (_self._tokenType) {
			case PortalClientTokenType.BearerClient:
			case PortalClientTokenType.BearerRopc:
				return { 'Authorization': _self._token };
			default:
				return null;
		}
	}

	this.getClient = function () {
		return _self.isValid() ? new PortalClient(_self.getTokenHeader(false), _self._baseUrl, _self._gatewayBaseUrl) : null;
	}

	return this;
};
var BCycle = BCycle || {};
const privatePortalClient = new PrivatePortalClient(PortalClientTokenType.BearerClient);
const userPortalClient = new PrivatePortalClient(PortalClientTokenType.BearerRopc);

function logout() {
    $.ajax({
        cache: false,
        async: true,
        type: "POST",
        url: "/api/Authenticate/Logout"
    }).then(
        function (result) {
            window.location.href = '/';
        },
        function (error) {
            var re = new RegExp(/^.*\//);
            window.location.href = re.exec(window.location.href);
        }
    );

	return false;
}

function getQueryStrings() {
	var returnValue = {};

	if (document.location.search != '') {
		$.each(document.location.search.substr(1).split('&'), function (index, queryString) {
			var keyValue = queryString.split('=');
			returnValue[keyValue[0].toString()] = keyValue[1].toString();
		});
	}

	return returnValue
}

function coalesce(value, valueIfNull) {
	if (value === null || value === undefined) {
		return valueIfNull;
	}
	return value;
}

function formatCurrency(value) {
	return (value < 0 ? '-$' : '$') + parseFloat(Math.abs(value), 10).toFixed(2).replace(/(\d)(?=(\d{3})+\.)/g, "$1,").toString();
}

if (!String.prototype.enumToString) {
    String.prototype.enumToString = function () {
        return this
            // Look for long acronyms and filter out the last letter
            .replace(/([A-Z]+)([A-Z][a-z])/g, ' $1 $2')
            // Look for lower-case letters followed by upper-case letters
            .replace(/([a-z\d])([A-Z])/g, '$1 $2')
            // Look for lower-case letters followed by numbers
            .replace(/([a-zA-Z])(\d)/g, '$1 $2')
            .replace(/^./, function (str) { return str.toUpperCase(); })
            // Remove any white space left around the word
            .trim();
    }
}
;
