import * as jwtDecode from "jwt-decode";
import http from "./httpService";
import { IShoppingCartStorageItem } from "../apiModels/ViewModels";

interface jwtToken {
	unique_name: number,
	role: string,
	firstName: string,
	lastName: string,
	nbf: number,
	exp: number,
	iat: number
}

const shoppingCartName = "ShoppingCart";

export function SetHttpAuthorizationToken() {
	http.setAuthorizationToken(GetAuthorizationToken());
}

// save authorization token to local storage
export function SetAuthorizationTokenLocalStorage(authorizationToken: string) {
	localStorage.setItem('authorizationToken', authorizationToken);
	SetHttpAuthorizationToken();
}

export function IsJwtForRefresh(): boolean {
	const jwt = GetObject();
	const exp = new Date(Date.now() + (5 * 60 * 1000));
	if (jwt === null) {
		return false;
	}

	return jwt.exp < exp.getTime() / 1000;
}

// delete authorization token from local storage
export function DeleteAuthorizationToken() {
	localStorage.removeItem('authorizationToken');
	SetHttpAuthorizationToken();
}

// get authorization token from local storage
function GetAuthorizationToken() {
	let authorizationToken = localStorage.getItem('authorizationToken');
	return authorizationToken !== null && !IsJwtExpired(authorizationToken) ? authorizationToken : null;
}

// Get user from jwtToken
export function GetObject(): jwtToken | null {
	const token = GetAuthorizationToken();
	if (token === null) {
		return null;
	}

	let user: jwtToken = jwtDecode.default(token);

	let keyNames = Object.keys(user);
	let roleKey = keyNames.find(i => i.includes("claims/role"));
	let uniqueNameKey = keyNames.find(i => i.includes("claims/name"));

	if (roleKey !== undefined && uniqueNameKey !== undefined) {
		user = renameProperty(user, roleKey!, 'role');
		user = renameProperty(user, uniqueNameKey!, 'unique_name');

		return user;
	}

	return null;
}

interface KeyPair {
	[key: string]: any;
}

function renameProperty(object: KeyPair , key: string, newKey: string): any {
	const clonedObj = { ...object };
	const targetKey = clonedObj[key];

	delete clonedObj[key];

	clonedObj[newKey] = targetKey;

	return clonedObj;
}

export function IsCustomerLoggedIn(): boolean {
	const user = GetObject();
	if (user === null) {
		return false;
	}
	// server mi posila nazev prop role a name jako "schemas..."
	// deje se tak v SecurityService metoda CreateToken
	return user.role === "Uživatel";
}

function IsJwtExpired(token: string): boolean {
	const jwt: jwtToken = jwtDecode.default(token);
	const result = jwt.exp < (Date.now() / 1000);

	if (result) {
		DeleteAuthorizationToken();
	}

	return result;
}

export function AddItemToShoppingCart(newItem: IShoppingCartStorageItem) {
	const cartItems: IShoppingCartStorageItem[] = GetShoppingCart();

	let item = cartItems.find(i => i.productID === newItem.productID);
	if (item !== undefined) {
		let itemIndex = cartItems.indexOf(item);

		cartItems[itemIndex].amount += newItem.amount;
	} else {
		cartItems.push(newItem);
	}
	
	SaveShoppingCart(cartItems);
}

export function DecreaseCartItemAmount(item: IShoppingCartStorageItem) {
	const cartItems: IShoppingCartStorageItem[] = GetShoppingCart();

	let cartItem = cartItems.find(i => i.productID === item.productID);
	if (cartItem !== undefined) {
		let index = cartItems.indexOf(cartItem);
		cartItems[index].amount -= item.amount;

		SaveShoppingCart(cartItems);
	}
}

export function DeleteCartItem(item: IShoppingCartStorageItem) {
	const cartItems: IShoppingCartStorageItem[] = GetShoppingCart()
		.filter(i => i.productID !== item.productID);

	SaveShoppingCart(cartItems);
}

export function SaveShoppingCart(cartItems: IShoppingCartStorageItem[]) {
	localStorage.setItem(shoppingCartName, JSON.stringify(cartItems));
}

export function RemoveShoppingCartFromLocalStorage() {
	localStorage.removeItem(shoppingCartName);
}

export function GetShoppingCart(): IShoppingCartStorageItem[] {
	const cartItems = localStorage.getItem(shoppingCartName);
	return cartItems !== null ? JSON.parse(cartItems) : [];
}