import { MantineColor } from "@mantine/core";
import { MESSAGE_MAX_TIME_TO_DELEVERED_S } from "../constants";

export function generateRandomKey(length: number): string {
	const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
	let result = '';
	const charactersLength = characters.length;
	for (let i = 0; i < length; i++) {
		result += characters.charAt(Math.floor(Math.random() * charactersLength));
	}
	return result;
}

export function murmurHash3_32_gc(key: string, seed: number = 0): number {
	let remainder = key.length & 3;
	let bytes = key.length - remainder;
	let h1 = seed;
	let c1 = 0xcc9e2d51;
	let c2 = 0x1b873593;
	let i = 0;

	while (i < bytes) {
		let k1 =
			((key.charCodeAt(i) & 0xff)) |
			((key.charCodeAt(++i) & 0xff) << 8) |
			((key.charCodeAt(++i) & 0xff) << 16) |
			((key.charCodeAt(++i) & 0xff) << 24);
		++i;

		k1 = (((k1 & 0xffff) * c1) + ((((k1 >>> 16) * c1) & 0xffff) << 16)) & 0xffffffff;
		k1 = (k1 << 15) | (k1 >>> 17);
		k1 = (((k1 & 0xffff) * c2) + ((((k1 >>> 16) * c2) & 0xffff) << 16)) & 0xffffffff;

		h1 ^= k1;
		h1 = (h1 << 13) | (h1 >>> 19);
		let h1b = (((h1 & 0xffff) * 5) + ((((h1 >>> 16) * 5) & 0xffff) << 16)) & 0xffffffff;
		h1 = ((h1b & 0xffff) + 0x6b64) + ((((h1b >>> 16) + 0xe654) & 0xffff) << 16);
	}

	let k1 = 0;

	switch (remainder) {
		case 3:
			k1 ^= (key.charCodeAt(i + 2) & 0xff) << 16;
		case 2:
			k1 ^= (key.charCodeAt(i + 1) & 0xff) << 8;
		case 1:
			k1 ^= (key.charCodeAt(i) & 0xff);

			k1 = (((k1 & 0xffff) * c1) + ((((k1 >>> 16) * c1) & 0xffff) << 16)) & 0xffffffff;
			k1 = (k1 << 15) | (k1 >>> 17);
			k1 = (((k1 & 0xffff) * c2) + ((((k1 >>> 16) * c2) & 0xffff) << 16)) & 0xffffffff;
			h1 ^= k1;
	}

	h1 ^= key.length;

	h1 ^= h1 >>> 16;
	h1 = (((h1 & 0xffff) * 0x85ebca6b) + ((((h1 >>> 16) * 0x85ebca6b) & 0xffff) << 16)) & 0xffffffff;
	h1 ^= h1 >>> 13;
	h1 = (((h1 & 0xffff) * 0xc2b2ae35) + ((((h1 >>> 16) * 0xc2b2ae35) & 0xffff) << 16)) & 0xffffffff;
	h1 ^= h1 >>> 16;

	return h1 >>> 0;
}

function hashCode(input: string) {
	let hash = 0;
	for (let i = 0; i < input.length; i += 1) {
		const char = input.charCodeAt(i);
		hash = (hash << 5) - hash + char;
		hash |= 0;
	}
	return hash;
}

const defaultColors: MantineColor[] = [
	'blue',
	'cyan',
	'grape',
	'green',
	'indigo',
	'lime',
	'orange',
	'pink',
	'red',
	'teal',
	'violet',
];

export function getInitialsColor(name: string, colors: MantineColor[] = defaultColors) {
	const hash = hashCode(name);
	const index = Math.abs(hash) % colors.length;
	return colors[index];
}

export function isMessageDeliveredByTime(messageTime: number, attachmentsCount: number): boolean {
	let maxMessageDeliveredTime = MESSAGE_MAX_TIME_TO_DELEVERED_S * 1000;;
	//((props.time && (Date.now() - props.time * 1000 > ((MESSAGE_MAX_TIME_TO_DELEVERED * 1000) * props.attachmentsCount || 1))
	if (attachmentsCount == 0) {
		let t = Date.now() - messageTime < maxMessageDeliveredTime;
		return t;
	}
	return Date.now() - messageTime < (maxMessageDeliveredTime * attachmentsCount);
}

export function filePrapareForNetworkTransfer(file : File){
	return new Promise<string>((resolve, reject) => {
		const reader = new FileReader();
		reader.onload = () => {
			if(!reader.result){
				reject();
				return;
			}
			resolve(reader.result.toString());
		}
		reader.readAsDataURL(file);
	})
}

export function humanFilesize(size: number) {
	const suffixes = ['B', 'KB', 'MB', 'GB'];
    if(size >= (1024 * 1024 * 1024)){
		return Math.floor(size / (1024 * 1024 * 1024)) + suffixes[3];
	}
	if(size >= (1024 * 1024)){
		return Math.floor(size / (1024 * 1024)) + suffixes[2];
	}
	if(size >= 1024){
		return Math.floor(size / 1024) + suffixes[1];
	}
	return size + suffixes[0];
}

export function imagePrepareForNetworkTransfer(file: File) {
	/**
	 * Нужно приводить все изображения к одному формату (png) чтобы избежать проблем с отображением
	 * в разных платформах (ios, android, web)
	 */
	return new Promise<string>((resolve, reject) => {
		const reader = new FileReader();
		reader.onload = async () => {
			if (!reader.result) {
				reject();
				return;
			}
			let base64 = reader.result.toString();
			if (file.type === 'image/png') {
				resolve(base64);
				return;
			}
			try {
				const jpegBlob = file;
				const pngBlob = await convertJpegBlobToPngBlob(jpegBlob);
				const pngBase64 = await blobToBase64(pngBlob);
				resolve(pngBase64);
			} catch (error) {
				reject(error);
			}
		};
		reader.readAsDataURL(file);
	});
}

export function blobToBase64(blob: Blob): Promise<string> {
	return new Promise((resolve, reject) => {
		const reader = new FileReader();
		reader.onloadend = () => {
			if (reader.result && typeof reader.result === "string") {
				resolve(reader.result);
			} else {
				reject("Failed to convert blob to base64");
			}
		};
		reader.onerror = reject;
		reader.readAsDataURL(blob);
	});
}

export function createBlobFromBase64Image(base64Image: string): Blob {
	    // Split the data URL to get the MIME type and the base64 data
    const parts = base64Image.split(';');
    const mimeType = parts[0].split(':')[1];
    const base64 = parts[1].split(',')[1];

    // Decode the base64 string
    const byteCharacters = atob(base64);
    const byteNumbers = new Array(byteCharacters.length);

    // Convert to a Uint8Array
    for (let i = 0; i < byteCharacters.length; i++) {
        byteNumbers[i] = byteCharacters.charCodeAt(i);
    }
    const byteArray = new Uint8Array(byteNumbers);

    // Create the Blob
    const blob = new Blob([byteArray], { type: mimeType });
    return blob;
}

export function convertJpegBlobToPngBlob(jpegBlob: Blob): Promise<Blob> {
  return new Promise((resolve, reject) => {
    const img = new Image();
    img.onload = () => {
      const canvas = document.createElement('canvas');
      canvas.width = img.width;
      canvas.height = img.height;
      const ctx = canvas.getContext('2d');
      ctx?.drawImage(img, 0, 0);

      // Convert the canvas content to a PNG Blob
      canvas.toBlob((pngBlob) => {
        if (pngBlob) {
          resolve(pngBlob);
        } else {
          reject(new Error('Failed to create PNG blob.'));
        }
      }, 'image/png', 1);
    };
    img.onerror = (error) => reject(error);
    img.src = URL.createObjectURL(jpegBlob);
  });
}

export function dotMessageIfNeeded(message: string, maxLength: number): string {
	if (message.length <= maxLength) {
		return message;
	}
	return message.substring(0, maxLength).trim() + '...';
}

export function dotCenterIfNeeded(message: string, maxLength : number, viewSymbols : number = 3) {
	if(message.length <= maxLength){
		return message;
	}
	return message.slice(0, viewSymbols) + "..." + message.slice(-viewSymbols)
}

export function isImage(blob : string) : boolean {
	if(!blob){
		return false;
	}
	return blob.startsWith('data:image/');
}
