import { WebSocket } from 'ws';
import { ungzip } from 'node-gzip';
import { getTimestamps } from '../common';
import { getSignature_XG } from '../utilities';

// https://www.npmjs.com/package/ws
// https://huobiapi.github.io/docs/usdt_swap/v1/en/#websocket-subscription-address

// LOCAL CONSTANTS
const isWS = false;
const purcent = 0.95; // deviation
const purcent_alt = 0.55; // alt_deviation
const period = 4; // timePeriod 1m, 5m
const buffer = [];
export const prefixes = [
	// 'BN_s',
	'BN_f',
	'BT_f',
	'HB_f',
	'KX_f',
	'MG_f',
	// 'MG_s',
];

// UPD Принт консоли
const printConsole_ = (params) => {
	const { date, purcent, prefix, tickers } = params;
	const arrChangesConsole = (arr) => {
		let message = '';
		arr.forEach((element) => {
			message += `${addPlusDeviation(element)}% `;
		});
		return message;
	};
	const prefixAllTickers = tickers.filter((item) => {
		return item.exchange === prefix;
	}).length;
	const cycleConsole = (arrow, arr) => {
		if (arr.length !== 0) {
			console.log(
				`	${prefix}: ${purcent}% | ALL:${prefixAllTickers} ${arrow}: ${arr.length}`
			);
			for (let i = 0; i < arr.length; i++) {
				// const devtn = addPlusDeviation(arr[i].deviation);
				const mes = `			 		| ${prefix}: ${
					+arr[i].currentPrice < 10
						? '_' + Number(arr[i].currentPrice).toFixed(7)
						: Number(arr[i].currentPrice).toFixed(7)
				} | ${arrChangesConsole(
					arr[i].changeHistory
					// )}| ${devtn}% | L:${arr[i].changeHistory.length} | ${
				)}| ${arr[i].ticker}`;
				console.log(mes);
			}
		}
	};
	const upTickers = tickers.filter((item) => {
		return (
			+item.deviation > 0 &&
			item.exchange === prefix &&
			Math.abs(item.deviation) > purcent
		);
	});
	const downTickers = tickers.filter((item) => {
		return (
			+item.deviation < 0 &&
			item.exchange === prefix &&
			Math.abs(item.deviation) > purcent
		);
	});
	cycleConsole('↑ UP', upTickers);
	cycleConsole('↓ DOWN', downTickers);
};

// Принт консоли
const printConsole = (params) => {
	const { prefix, purcent, buffer } = params;
	if (Math.abs(buffer.deviation) > purcent) {
		const devtn =
			+buffer.deviation > 0 ? '+' + +buffer.deviation : buffer.deviation;
		console.log(
			getTimestamps() +
				' | ' +
				prefix +
				': ' +
				Number(buffer.currentPrice).toFixed(5) +
				' | ' +
				devtn +
				'% | ' +
				buffer.ticker
		);
	}
};

// PingPong обработчик
const pingPongHandler = (params) => {
	const { prefix, ws, timestamp, count } = params;
	if (prefix === 'HB_f') {
		ws.send(JSON.stringify({ pong: timestamp }));
	} else if (prefix === 'MG_f') {
		ws.send(JSON.stringify({ method: 'ping' }));
	}
	if (count !== 0) {
		const mes = `${prefix}: ping/pong | ${getTimestamps()} | count: ${count}`;
		console.log(mes);
	}
};

// Обработчик массива ChangeHistory
const handlerChangeHistory = (arrChanges, devtn) => {
	arrChanges.push(devtn);
	arrChanges.length > 4 ? delete arrChanges.shift() : arrChanges;
	return arrChanges;
};

// add + Deviation
const addPlusDeviation = (value) => {
	const result =
		+value >= 0
			? `+${Number(value).toFixed(2)}`
			: Number(value).toFixed(2);
	return result;
};

// ОБработчик временного хранилища
const bufferHandler = (params) => {
	const { idx, symbol, timestamp, price, prefix } = params;
	// если тикер не нашелся, добавляем тикер в буфер
	if (idx === -1) {
		buffer.push({
			ticker: symbol,
			previewPrice: 0,
			currentPrice: price,
			previewTime: new Date(),
			currentTime: timestamp,
			exchange: prefix,
			changeHistory: [],
		});
	} else {
		// если тикер нашелся idx !== -1
		buffer[idx].currentTime = timestamp;
		// для period минут
		if (
			buffer[idx].currentTime - buffer[idx].previewTime >
			60000 * period
		) {
			buffer[idx].previewTime = buffer[idx].currentTime;
			buffer[idx].currentTime = timestamp;
			buffer[idx].previewPrice = buffer[idx].currentPrice;
			buffer[idx].currentPrice = price;
			const arr = buffer[idx].changeHistory.slice();
			const deviation =
				+buffer[idx].previewPrice > +buffer[idx].currentPrice
					? (
							(+buffer[idx].currentPrice * 100) /
								+buffer[idx].previewPrice -
							100
					  ).toFixed(2)
					: (
							100 -
							(+buffer[idx].previewPrice * 100) / +buffer[idx].currentPrice
					  ).toFixed(2);
			buffer[idx].deviation = deviation;
			buffer[idx].changeHistory = handlerChangeHistory(arr, deviation);
			// если отклонение цены по м5 больше 1%
			// printConsole({ prefix, purcent, buffer: buffer[idx] });
		}
	}
};

const getTradingBalance = (method) => {
	const wsURL = 'wss://api.xeggex.com';
	const ws = new WebSocket(wsURL);

	ws.on('open', function open() {
		const config = {
			method,
			params: {},
		};
		ws.send(JSON.stringify(config));
		ws.on('message', function message(res) {
			if (res) {
				const msg = JSON.parse(res);
				console.log(msg);
			}
		});
	});
};

export const getUserProvidedId = (apiKeys) => {
	const wsURL = 'wss://api.xeggex.com';
	const ws = new WebSocket(wsURL);
	const nonce = Math.random() * 100 + 'N1g287gL8YOwDZr';
	ws.on('open', function open() {
		const config = {
			method: 'login',
			params: {
				// algo: 'BASIC',
				// pKey: apiKeys.publicKey,
				// sKey: apiKeys.secretKey,
				algo: 'HS256',
				pKey: apiKeys.publicKey,
				nonce,
				signature: getSignature_XG(nonce, apiKeys.secretKey),
			},
		};
		ws.send(JSON.stringify(config));
	});

	ws.on('message', function message(response) {
		if (response) {
			// console.log(response);
			const msgs = JSON.parse(response);
			console.log(msgs);
			if (msgs.result) {
				getTradingBalance('getTradingBalance');
				// console.log('getTradingBalance');
			}
		}
	});
};

// запуск WebSoket Binance || Bybit || Huobi || OKX || Mexc
export const startWebSocket = (prefix) => {
	console.log(`${getTimestamps()} | ${prefix}: webSocket started!`);
	if (prefix === '++++') {
	} else if (prefix === 'BN_s') {
		const spotBN = [
			'1inchusdt',
			'aaveusdt',
			'achusdt',
			'adausdt',
			'agldusdt',
			'akrousdt',
			'alcxusdt',
			'algousdt',
			'aliceusdt',
			'alpacausdt',
			'alphausdt',
			'ampusdt',
			'ankrusdt',
			'antusdt',
			'apeusdt',
			'api3usdt',
			'aptusdt',
			'ardrusdt',
			'arpausdt',
			'arusdt',
			'astrusdt',
			'atausdt',
			'atomusdt',
			'auctionusdt',
			'audiousdt',
			'autousdt',
			'avausdt',
			'avaxusdt',
			'axsusdt',
			'badgerusdt',
			'bakeusdt',
			'balusdt',
			'bandusdt',
			'batusdt',
			'bchusdt',
			'belusdt',
			'betausdt',
			'bicousdt',
			'blzusdt',
			'bnbusdt',
			'bntusdt',
			'bnxusdt',
			'bondusdt',
			'bswusdt',
			'btcusdt',
			'bttcusdt',
			'burgerusdt',
			'busdusdt',
			'c98usdt',
			'cakeusdt',
			'celousdt',
			'celrusdt',
			'cfxusdt',
			'chessusdt',
			'chrusdt',
			'chzusdt',
			'ckbusdt',
			'clvusdt',
			'cocosusdt',
			'cocosusdt',
			'compusdt',
			'cosusdt',
			'crvusdt',
			'ctkusdt',
			'ctsiusdt',
			'ctxcusdt',
			'cvpusdt',
			'cvxusdt',
			'darusdt',
			'dashusdt',
			'datausdt',
			'dcrusdt',
			'degousdt',
			'dentusdt',
			'dexeusdt',
			'dgbusdt',
			'diausdt',
			'dockusdt',
			'dodousdt',
			'dotusdt',
			'drepusdt',
			'duskusdt',
			'dydxusdt',
			'egldusdt',
			'elfusdt',
			'enjusdt',
			'ensusdt',
			'eosusdt',
			'epxusdt',
			'ernusdt',
			'etcusdt',
			'ethusdt',
			'farmusdt',
			'fetusdt',
			'fidausdt',
			'filusdt',
			'fiousdt',
			'firousdt',
			'fisusdt',
			'flmusdt',
			'flowusdt',
			'fluxusdt',
			'forthusdt',
			'forusdt',
			'ftmusdt',
			'fxsusdt',
			'galausdt',
			'galusdt',
			// 'glmrusdt',
			// 'gmtusdt',
			// 'gmxusdt',
			// 'grtusdt',
			// 'gtcusdt',
			// 'hardusdt',
			// 'hbarusdt',
			// 'hifiusdt',
			// 'highusdt',
			// 'hiveusdt',
			// 'hotusdt',
			// 'icpusdt',
			// 'icxusdt',
			// 'idexusdt',
			// 'ilvusdt',
			// 'imxusdt',
			// 'injusdt',
			// 'iostusdt',
			// 'iotxusdt',
			// 'ioтаusdt',
			// 'irisusdt',
			// 'jasmyusdt',
			// 'joeusdt',
			// 'jstusdt',
			// 'kavausdt',
			// 'kdausdt',
			// 'klayusdt',
			// 'kmdusdt',
			// 'kncusdt',
			// 'kp3rusdt',
			// 'ksmusdt',
			// 'laziousdt',
			// 'ldousdt',
			// 'leverusdt',
			// 'linausdt',
			// 'linkusdt',
			// 'litusdt',
			// 'loкаusdt',
			// 'lptusdt',
			// 'lrcusdt',
			// 'lskusdt',
			// 'ltcusdt',
			// 'ltousdt',
			// 'lunausdt',
			// 'luncusdt',
			// 'magicusdt',
			// 'manausdt',
			// 'masкusdt',
			// 'maticusdt',
			// 'mblusdt',
			// 'mboxusdt',
			// 'mcusdt',
			// 'mdtusdt',
			// 'mdxusdt',
			// 'minausdt',
			// 'mkrusdt',
			// 'mlnusdt',
			// 'mobusdt',
			// 'movrusdt',
			// 'mtlusdt',
			// 'nearusdt',
			// 'neousdt',
			// 'nexousdt',
			// 'nknusdt',
			// 'nmrusdt',
			// 'nulsusdt',
			// 'oceanusdt',
			// 'ognusdt',
			// 'ogusdt',
			// 'omusdt',
			// 'oneusdt',
			// 'ongusdt',
			// 'ontusdt',
			// 'ookiusdt',
			// 'opusdt',
			// 'ornusdt',
			// 'osmousdt',
			// 'oxtusdt',
			// 'paxgusdt',
			// 'peopleusdt',
			// 'peopleusdt',
			// 'perpusdt',
			// 'phausdt',
			// 'plausdt',
			// 'pntusdt',
			// 'polsusdt',
			// 'polyxusdt',
			// 'pondusdt',
			// 'portousdt',
			// 'powrusdt',
			// 'pundixusdt',
			// 'pyrusdt',
			// 'qiusdt',
			// 'qntusdt',
			// 'qtumusdt',
			// 'quickusdt',
			// 'radusdt',
			// 'rareusdt',
			// 'reefusdt',
			// 'reiusdt',
			// 'renusdt',
			// 'requsdt',
			// 'rlcusdt',
			// 'rndrusdt',
			// 'roseusdt',
			// 'rplusdt',
			// 'rsrusdt',
			// 'runeusdt',
			// 'rvnusdt',
			// 'sandusdt',
			// 'santosusdt',
			// 'scrtusdt',
			// 'scusdt',
			// 'sfpusdt',
			// 'shibusdt',
			// 'sklusdt',
			// 'slpusdt',
			// 'snxusdt',
			// 'solusdt',
			// 'spellusdt',
			// 'stgusdt',
			// 'stmxusdt',
			// 'storjusdt',
			// 'stptusdt',
			// 'straxusdt',
			// 'stxusdt',
			// 'sunusdt',
			// 'superusdt',
			// 'sushiusdt',
			// 'sxpusdt',
			// 'sysusdt',
			// 'tfuelusdt',
			// 'thetausdt',
			// 'tkousdt',
			// 'tlmusdt',
			// 'tomousdt',
			// 'trbusdt',
			// 'troyusdt',
			// 'truusdt',
			// 'trxusdt',
			// 'tusdt',
			// 'tvkusdt',
			// 'twtusdt',
			// 'umausdt',
			// 'unfiusdt',
			// 'uniusdt',
			// 'utkusdt',
			// 'vetusdt',
			// 'viteusdt',
			'voxelusdt',
			'vthousdt',
			'wanusdt',
			'wavesusdt',
			'waxpusdt',
			'wingusdt',
			'winusdt',
			'wnxmusdt',
			'woousdt',
			'wrxusdt',
			'wtcusdt',
			'xecusdt',
			'xemusdt',
			'xlmusdt',
			'xmrusdt',
			'xrpusdt',
			'xtzusdt',
			'xvsusdt',
			'yfiusdt',
			'yggusdt',
			'yggusdt',
			'zecusdt',
			'zenusdt',
			'zenusdt',
			'zilusdt',
			'zrxusdt',
		];
		const wsURL_1 = 'wss://fstream.binance.com/';
		const aggrSTR = spotBN
			.map((item) => {
				return item + '@kline_1m';
			})
			.join('/');

		const ws = new WebSocket(`${wsURL_1}stream?streams=${aggrSTR}`);

		ws.on('message', (data) => {
			if (data) {
				const msgs = JSON.parse(data);
				// console.log(msgs);
				if (msgs.data) {
					const symbol = msgs.data.s;
					const timestamp = msgs.data.E;
					const price = msgs.data.k.c;
					// поиск по наличию полученного тикера
					const idx = buffer.findIndex(
						(i) => i.ticker === symbol && i.exchange === prefix
					);
					// console.log(prefix, symbol, price, new Date(timestamp));
					bufferHandler({
						idx,
						symbol,
						timestamp,
						price,
						prefix,
					});
				}
			}
		});
	} else if (prefix === 'BN_f') {
		const wsURL_1 = 'wss://fstream.binance.com/';
		const perpBN_1 = [
			'1000flokiusdt',
			'1000luncbusd',
			'1000luncusdt',
			'1000pepeusdt',
			'1000shibusdt',
			'1000xecusdt',
			'1inchusdt',
			'aaveusdt',
			'achusdt',
			'adausdt',
			'agixusdt',
			'algousdt',
			'aliceusdt',
			'alphausdt',
			'ambusdt',
			'ankrusdt',
			'antusdt',
			'apeusdt',
			'api3usdt',
			'aptusdt',
			'arbusdt',
			'arpausdt',
			'arusdt',
			'astrusdt',
			'atausdt',
			'atomusdt',
			'audiousdt',
			'avaxusdt',
			'axsusdt',
			'bakeusdt',
			'balusdt',
			'bandusdt',
			'batusdt',
			'bchusdt',
			'belusdt',
			'bluebirdusdt',
			'blurusdt',
			'blzusdt',
			'bnbusdt',
			'bnxusdt',
			'btcdomusdt',
			'btcstusdt',
			'btcusdt',
			'btsusdt',
			'c98usdt',
			'celousdt',
			'celrusdt',
			'cfxusdt',
			'chrusdt',
			'chzusdt',
			'ckbusdt',
			'cocosusdt',
			'compusdt',
			'cotiusdt',
			'crvusdt',
			'ctkusdt',
			'ctsiusdt',
			'cvcusdt',
			'cvxusdt',
			'darusdt',
			'dashusdt',
			'defiusdt',
			'dentusdt',
			'dgbusdt',
			'dogeusdt',
			'dotusdt',
			'duskusdt',
			'dydxusdt',
			'eduusdt',
			'egldusdt',
			'enjusdt',
			'ensusdt',
			'eosusdt',
			'etcusdt',
			'ethusdt',
			'fetusdt',
			'filusdt',
			'flmusdt',
			'flowusdt',
			'footballusdt',
			'ftmusdt',
			'fttusdt',
			'fxsusdt',
			'galausdt',
			'galusdt',
			'gmtusdt',
			'gmxusdt',
			'grtusdt',
			'gtcusdt',
			'hbarusdt',
			'hftusdt',
			'highusdt',
			'hntusdt',
			'hookusdt',
			'hotusdt',
			'icpusdt',
		];
		const perpBN_2 = [
			'icxusdt',
			'idexusdt',
			'idusdt',
			'imxusdt',
			'injusdt',
			'iostusdt',
			'iotausdt',
			'iotxusdt',
			'jasmyusdt',
			'joeusdt',
			'kavausdt',
			'klayusdt',
			'kncusdt',
			'ksmusdt',
			'ldousdt',
			'leverusdt',
			'linausdt',
			'linkusdt',
			'litusdt',
			'lptusdt',
			'lqtyusdt',
			'lrcusdt',
			'ltcusdt',
			'luna2usdt',
			'magicusdt',
			'manausdt',
			'maskusdt',
			'maticusdt',
			'minausdt',
			'mkrusdt',
			'mtlusdt',
			'nearusdt',
			'neousdt',
			'nknusdt',
			'oceanusdt',
			'ognusdt',
			'omgusdt',
			'oneusdt',
			'ontusdt',
			'opusdt',
			'peopleusdt',
			'perpusdt',
			'phbusdt',
			'qntusdt',
			'qtumusdt',
			'radusdt',
			'rayusdt',
			'rdntusdt',
			'reefusdt',
			'renusdt',
			'rlcusdt',
			'rndrusdt',
			'roseusdt',
			'rsrusdt',
			'runeusdt',
			'rvnusdt',
			'sandusdt',
			'scusdt',
			'sfpusdt',
			'sklusdt',
			'snxusdt',
			'solusdt',
			'spellusdt',
			'srmusdt',
			'ssvusdt',
			'stgusdt',
			'stmxusdt',
			'storjusdt',
			'stxusdt',
			'suiusdt',
			'sushiusdt',
			'sxpusdt',
			'thetausdt',
			'tlmusdt',
			'tomousdt',
			'trbusdt',
			'truusdt',
			'trxusdt',
			'tusdt',
			'umausdt',
			'unfiusdt',
			'uniusdt',
			'usdcusdt',
			'vetusdt',
			'wavesusdt',
			'woousdt',
			'xemusdt',
			'xlmusdt',
			'xmrusdt',
			'xrpusdt',
			'xtzusdt',
			'xvsusdt',
			'yfiusdt',
			'zecusdt',
			'zenusdt',
			'zilusdt',
			'zrxusdt',
		];
		const aggrSTR1 = perpBN_1
			.map((item) => {
				return item + '_perpetual@continuousKline_1m';
			})
			.join('/');
		const aggrSTR2 = perpBN_2
			.map((item) => {
				return item + '_perpetual@continuousKline_1m';
			})
			.join('/');

		const ws1 = new WebSocket(`${wsURL_1}stream?streams=${aggrSTR1}`);
		const ws2 = new WebSocket(`${wsURL_1}stream?streams=${aggrSTR2}`);

		ws1.on('message', (data) => {
			if (data) {
				const msgs = JSON.parse(data);
				// console.log('ws1: ' + msgs.data.ps);
				if (msgs.data) {
					const symbol = msgs.data.ps;
					const timestamp = msgs.data.E;
					const price = msgs.data.k.c;
					// поиск по наличию полученного тикера
					const idx = buffer.findIndex(
						(i) => i.ticker === symbol && i.exchange === prefix
					);
					bufferHandler({
						idx,
						symbol,
						timestamp,
						price,
						prefix,
					});
				}
			}
		});

		ws2.on('message', (data) => {
			if (data) {
				const msgs = JSON.parse(data);
				// console.log('ws2: ' + msgs.data.ps);
				if (msgs.data) {
					const symbol = msgs.data.ps;
					const timestamp = msgs.data.E;
					const price = msgs.data.k.c;
					// поиск по наличию полученного тикера
					const idx = buffer.findIndex(
						(i) => i.ticker === symbol && i.exchange === prefix
					);
					bufferHandler({
						idx,
						symbol,
						timestamp,
						price,
						prefix,
					});
				}
			}
		});
	} else if (prefix === 'BT_f') {
		const perpBT = [
			'10000LADYSUSDT',
			'10000NFTUSDT',
			'1000BONKUSDT',
			'1000BTTUSDT',
			'1000FLOKIUSDT',
			'1000LUNCUSDT',
			'1000PEPEUSDT',
			'1000XECUSDT',
			'1INCHUSDT',
			'AAVEUSDT',
			'ACHUSDT',
			'ADAUSDT',
			'AGIXUSDT',
			'AGLDUSDT',
			'AKROUSDT',
			'ALGOUSDT',
			'ALICEUSDT',
			'ALPHAUSDT',
			'ANKRUSDT',
			'ANTUSDT',
			'APEUSDT',
			'API3USDT',
			'APTUSDT',
			'ARBUSDT',
			'ARPAUSDT',
			'ARUSDT',
			'ASTRUSDT',
			'ATOMUSDT',
			'AUDIOUSDT',
			'AVAXUSDT',
			'AXSUSDT',
			'BAKEUSDT',
			'BALUSDT',
			'BANDUSDT',
			'BATUSDT',
			'BCHUSDT',
			'BELUSDT',
			'BICOUSDT',
			'BITUSDT',
			'BLURUSDT',
			'BLZUSDT',
			'BNBUSDT',
			'BNXUSDT',
			'BOBAUSDT',
			'BSVUSDT',
			'BSWUSDT',
			'BTCUSDT',
			'BUSDUSDT',
			'C98USDT',
			'CEEKUSDT',
			'CELOUSDT',
			'CELRUSDT',
			'CFXUSDT',
			'CHRUSDT',
			'CHZUSDT',
			'CKBUSDT',
			'COCOSUSDT',
			'COMPUSDT',
			'COREUSDT',
			'COTIUSDT',
			'CREAMUSDT',
			'CROUSDT',
			'CRVUSDT',
			'CTCUSDT',
			'CTKUSDT',
			'CTSIUSDT',
			'CVCUSDT',
			'CVXUSDT',
			'DARUSDT',
			'DASHUSDT',
			'DENTUSDT',
			'DGBUSDT',
			'DODOUSDT',
			'DOGEUSDT',
			'DOTUSDT',
			'DUSKUSDT',
			'DYDXUSDT',
			'EDUUSDT',
			'EGLDUSDT',
			'ENJUSDT',
			'ENSUSDT',
			'EOSUSDT',
			'ETCUSDT',
			'ETHUSDT',
			'ETHWUSDT',
			'FETUSDT',
			'FILUSDT',
			'FITFIUSDT',
			'FLMUSDT',
			'FLOWUSDT',
			'FLRUSDT',
			'FTMUSDT',
			'FXSUSDT',
			'GALAUSDT',
			'GALUSDT',
			'GFTUSDT',
			'GLMRUSDT',
			'GMTUSDT',
			'GMXUSDT',
			'GPTUSDT',
			'GRTUSDT',
			'GTCUSDT',
			'HBARUSDT',
			'HFTUSDT',
			'HIGHUSDT',
			'HNTUSDT',
			'HOOKUSDT',
			'HOTUSDT',
			'ICPUSDT',
			'ICXUSDT',
			'IDUSDT',
			'ILVUSDT',
			'IMXUSDT',
			'INJUSDT',
			'IOSTUSDT',
			'IOTAUSDT',
			'IOTXUSDT',
			'JASMYUSDT',
			'JOEUSDT',
			'JSTUSDT',
			'KAVAUSDT',
			'KDAUSDT',
			'KLAYUSDT',
			'KNCUSDT',
			'KSMUSDT',
			'LDOUSDT',
			'LINAUSDT',
			'LINKUSDT',
			'LITUSDT',
			'LOOKSUSDT',
			'LPTUSDT',
			'LQTYUSDT',
			'LRCUSDT',
			'LTCUSDT',
			'LUNA2USDT',
			'MAGICUSDT',
			'MANAUSDT',
			'MASKUSDT',
			'MATICUSDT',
			'MINAUSDT',
			'MKRUSDT',
			'MTLUSDT',
			'NEARUSDT',
			'NEOUSDT',
			'NKNUSDT',
			'OCEANUSDT',
			'OGNUSDT',
			'OMGUSDT',
			'ONEUSDT',
			'ONTUSDT',
			'OPUSDT',
			'PAXGUSDT',
			'PEOPLEUSDT',
			'QTUMUSDT',
			'RDNTUSDT',
			'REEFUSDT',
			'RENUSDT',
			'REQUSDT',
			'RLCUSDT',
			'RNDRUSDT',
			'ROSEUSDT',
			'RPLUSDT',
			'RSRUSDT',
			'RSS3USDT',
			'RUNEUSDT',
			'RVNUSDT',
			'SANDUSDT',
			'SCRTUSDT',
			'SCUSDT',
			'SFPUSDT',
			'SHIB1000USDT',
			'SKLUSDT',
			'SLPUSDT',
			'SNXUSDT',
			'SOLUSDT',
			'SPELLUSDT',
			'SSVUSDT',
			'STGUSDT',
			'STMXUSDT',
			'STORJUSDT',
			'STXUSDT',
			'SUIUSDT',
			'SUNUSDT',
			'SUSHIUSDT',
			'SWEATUSDT',
			'SXPUSDT',
			'THETAUSDT',
			'TLMUSDT',
			'TOMOUSDT',
			'TRBUSDT',
			'TRUUSDT',
			'TRXUSDT',
			'TUSDT',
			'TWTUSDT',
			'UNFIUSDT',
			'UNIUSDT',
			'USDCUSDT',
			'VETUSDT',
			'WAVESUSDT',
			'WOOUSDT',
			'XCNUSDT',
			'XEMUSDT',
			'XLMUSDT',
			'XMRUSDT',
			'XNOUSDT',
			'XRPUSDT',
			'XTZUSDT',
			'YFIUSDT',
			'YGGUSDT',
			'ZECUSDT',
			'ZENUSDT',
			'ZILUSDT',
			'ZRXUSDT',
		];
		const argsArr = perpBT.map((item) => {
			return 'instrument_info.100ms.' + item;
		});
		const wsURL_1 = 'wss://stream.bybit.com/realtime_public';
		// const wsURL_2 = 'wss://stream.bybit.com/spot/public/v3';
		const ws = new WebSocket(wsURL_1);

		ws.on('open', function open() {
			const params = {
				op: 'subscribe',
				// args: ['trade.BTCUSDT', 'trade.XRPUSDT'],
				// args: ['tickers.BTCUSDT', 'tickers.XRPUSDT'],
				// args: [
				// 	'instrument_info.100ms.AXSUSDT',
				// 	'instrument_info.100ms.XRPUSDT',
				// ],
				// args: ['candle.5.AXSUSDT'],
				args: argsArr,
				// args: ['liquidation.BTCUSDT', 'liquidation.XRPUSDT'],
			};
			ws.send(JSON.stringify(params));
		});

		ws.on('message', function message(data) {
			const msgs = JSON.parse(data);
			if (msgs.type === 'delta' && msgs.data.update[0].last_price) {
				const symbol = msgs.data.update[0].symbol;
				const timestamp = Date.parse(msgs.data.update[0].updated_at);
				const price = msgs.data.update[0].last_price;
				// поиск по наличию полученного тикера
				const idx = buffer.findIndex(
					(i) => i.ticker === symbol && i.exchange === prefix
				);
				bufferHandler({
					idx,
					symbol,
					timestamp,
					price,
					prefix,
				});
			}
		});
	} else if (prefix === 'HB_f') {
		let countPingPong = 0;
		const perpHB = [
			'1INCH-USDT',
			'AAVE-USDT',
			'ADA-USDT',
			'ALGO-USDT',
			'APE-USDT',
			'APT-USDT',
			'ATOM-USDT',
			'AVAX-USDT',
			'AXS-USDT',
			'BCH-USDT',
			'BNB-USDT',
			'BTC-USDT',
			'C98-USDT',
			'CHZ-USDT',
			'CRV-USDT',
			'CTSI-USDT',
			'DOGE-USDT',
			'DOT-USDT',
			'DYDX-USDT',
			'ENS-USDT',
			'EOS-USDT',
			'ETC-USDT',
			'ETH-USDT',
			'ETHW-USDT',
			'FIL-USDT',
			'FTM-USDT',
			'GAL-USDT',
			'GRT-USDT',
			'HT-USDT',
			'ICP-USDT',
			'IMX-USDT',
			'JST-USDT',
			'KAVA-USDT',
			'KSM-USDT',
			'LINK-USDT',
			'LRC-USDT',
			'LTC-USDT',
			'LUNA-USDT',
			'LUNC-USDT',
			'MANA-USDT',
			'MATIC-USDT',
			'NEAR-USDT',
			'ONE-USDT',
			'OP-USDT',
			'PEOPLE-USDT',
			'QNT-USDT',
			'REN-USDT',
			'SAND-USDT',
			'SHIB-USDT',
			'SNX-USDT',
			'SOL-USDT',
			'SUSHI-USDT',
			'THETA-USDT',
			'TON-USDT',
			'TRX-USDT',
			'UNI-USDT',
			'WAVES-USDT',
			'WIN-USDT',
			'XRP-USDT',
			'YFI-USDT',
		];
		const wsURL_1 = 'wss://api.hbdm.com/linear-swap-ws';
		// const wsURL_2 = 'wss://api.huobi.pro/ws';
		const ws = new WebSocket(wsURL_1);

		ws.on('open', function open() {
			for (let i = 0; i < perpHB.length; i++) {
				const params = {
					// sub: 'market.BTC-USDT.kline.1min',
					// sub: 'market.btcusdt.kline.1min',
					// sub: [
					// 	'market.btcusdt.trade.detail',
					// 	'market.ltcusdt.trade.detail',
					// ],
					// sub: `market.${perpHB[i]}.trade.detail`,
					sub: `market.${perpHB[i]}.kline.1min`,
				};
				ws.send(JSON.stringify(params));
			}
		});

		ws.on('message', async function message(data) {
			if (data) {
				const decompressed = await ungzip(data);
				const msgs = JSON.parse(decompressed.toString());
				// console.log(msgs);
				if (msgs.ping) {
					countPingPong++;
					pingPongHandler({
						prefix,
						ws,
						timestamp: msgs.ping,
						count: countPingPong % 50 ? 0 : countPingPong,
					});
					// console.log(prefix + ': pong');
				} else if (msgs.tick) {
					const symbol = msgs.ch.split('.')[1];
					const timestamp = msgs.ts;
					const price = msgs.tick.close.toString();
					// поиск по наличию полученного тикера
					const idx = buffer.findIndex(
						(i) => i.ticker === symbol && i.exchange === prefix
					);
					bufferHandler({
						idx,
						symbol,
						timestamp,
						price,
						prefix,
					});
				}
			}
		});
	} else if (prefix === 'KX_f') {
		const perpKX = [
			'1INCH-USDT',
			'AAVE-USDT',
			'ADA-USDT',
			'AGLD-USDT',
			'ALGO-USDT',
			'ALPHA-USDT',
			'ANT-USDT',
			'APE-USDT',
			'API3-USDT',
			'APT-USDT',
			'ATOM-USDT',
			'AVAX-USDT',
			'AXS-USDT',
			'BADGER-USDT',
			'BAL-USDT',
			'BAND-USDT',
			'BAT-USDT',
			'BCH-USDT',
			'BICO-USDT',
			'BNB-USDT',
			'BNT-USDT',
			'BSV-USDT',
			'BTC-USDT',
			'CEL-USDT',
			'CELO-USDT',
			'CFX-USDT',
			'CHZ-USDT',
			'COMP-USDT',
			'CRO-USDT',
			'CRV-USDT',
			'CSPR-USDT',
			'CVC-USDT',
			'DASH-USDT',
			'DOGE-USDT',
			'DOME-USDT',
			'DORA-USDT',
			'DOT-USDT',
			'DYDX-USDT',
			'EGLD-USDT',
			'ENJ-USDT',
			'ENS-USDT',
			'EOS-USDT',
			'ETC-USDT',
			'ETH-USDT',
			'ETHW-USDT',
			'FIL-USDT',
			'FITFI-USDT',
			'FLM-USDT',
			'FTM-USDT',
			'GALA-USDT',
			'GMT-USDT',
			'GODS-USDT',
			'GRT-USDT',
			'ICP-USDT',
			'IMX-USDT',
			'IOST-USDT',
			'IOTA-USDT',
			'JST-USDT',
			'KISHU-USDT',
			'KLAY-USDT',
			'KNC-USDT',
			'KSM-USDT',
			'LINK-USDT',
			'LOOKS-USDT',
			'LPT-USDT',
			'LRC-USDT',
			'LTC-USDT',
			'LUNA-USDT',
			'LUNC-USDT',
			'MANA-USDT',
			'MASK-USDT',
			'MINA-USDT',
			'MKR-USDT',
			'NEAR-USDT',
			'NEO-USDT',
			'NFT-USDT',
			'OMG-USDT',
			'ONT-USDT',
			'OP-USDT',
			'PEOPLE-USDT',
			'PERP-USDT',
			'QTUM-USDT',
			'REN-USDT',
			'RSR-USDT',
			'RVN-USDT',
			'SAND-USDT',
			'SHIB-USDT',
			'SLP-USDT',
			'SNX-USDT',
			'SOL-USDT',
			'STARL-USDT',
			'STORJ-USDT',
			'SUSHI-USDT',
			'SWEAT-USDT',
			'THETA-USDT',
			'TON-USDT',
			'TRB-USDT',
			'TRX-USDT',
			'UMA-USDT',
			'UNI-USDT',
			'USTC-USDT',
			'WAVES-USDT',
			'XCH-USDT',
			'XLM-USDT',
			'XMR-USDT',
			'XRP-USDT',
			'XTZ-USDT',
			'YFI-USDT',
			'YFII-USDT',
			'YGG-USDT',
			'ZEC-USDT',
			'ZEN-USDT',
			'ZIL-USDT',
			'ZRX-USDT',
			'МАTIC-USDT',
		];
		const argsArr = perpKX.map((item) => {
			return { channel: 'tickers', instId: item + '-SWAP' };
		});
		const wsURL_1 = 'wss://ws.okx.com:8443/ws/v5/public';
		// const wsURL_2 = 'wss://ws.okx.com:8443/ws/v5/private';
		const ws = new WebSocket(wsURL_1);

		ws.on('open', function open() {
			const params = {
				op: 'subscribe',
				args: argsArr,
				// args: [
				// 	{
				// 		channel: 'tickers',
				// 		instId: 'LTC-USDT-SWAP',
				// 	},
				// 	{
				// 		channel: 'tickers',
				// 		instId: 'BTC-USDT-SWAP',
				// 	},
				// ],
			};
			ws.send(JSON.stringify(params));
		});

		ws.on('message', function message(data) {
			const msgs = JSON.parse(data);
			if (msgs.data && msgs.data[0].last) {
				const symbol = msgs.data[0].instId.split('-SWAP')[0];
				const timestamp = msgs.data[0].ts;
				const price = msgs.data[0].last;
				// поиск по наличию полученного тикера
				const idx = buffer.findIndex(
					(i) => i.ticker === symbol && i.exchange === prefix
				);
				bufferHandler({
					idx,
					symbol,
					timestamp,
					price,
					prefix,
				});
			}
		});
	} else if (prefix === 'MG_s') {
		const perpMG = ['BTCUSDT', 'ETHUSDT', 'LTCUSDT'];
		const argsArr = perpMG.map((item) => {
			return `spot@public.kline.v3.api@${item}@Min1`;
		});
		const wsURL_1 = 'wss://wbs.mexc.com/ws';
		const ws = new WebSocket(wsURL_1);

		ws.on('open', function open() {
			const params = {
				method: 'SUBSCRIPTION',
				params: argsArr,
				// params: [
				// 	'spot@public.kline.v3.api@BTCUSDT@Min1',
				// 	'spot@public.kline.v3.api@ETHUSDT@Min1',
				// ],
			};
			ws.send(JSON.stringify(params));
		});

		ws.on('message', function message(data) {
			const msgs = JSON.parse(data);
			console.log(msgs);
			if (msgs.data && msgs.data[0].last) {
				const symbol = msgs.data[0].instId.split('-SWAP')[0];
				const timestamp = msgs.data[0].ts;
				const price = msgs.data[0].last;
				// поиск по наличию полученного тикера
				const idx = buffer.findIndex(
					(i) => i.ticker === symbol && i.exchange === prefix
				);
				bufferHandler({
					idx,
					symbol,
					timestamp,
					price,
					prefix,
				});
			}
		});
	} else if (prefix === 'MG_f') {
		let countPingPong = 0;
		// const perpMG = ['BTC_USDT', 'ETH_USDT', 'LTC_USDT'];
		// const argsArr = perpMG.map((item) => {
		// 	return `spot@public.kline.v3.api@${item}@Min1`;
		// });
		const wsURL_1 = 'wss://contract.mexc.com/ws';
		const ws = new WebSocket(wsURL_1);

		ws.on('open', function open() {
			const params = {
				method: 'sub.tickers',
				// method: 'sub.kline',
				// params: argsArr,
				// param: {
				// 	symbol: 'BTC_USDT',
				// 	interval: 'Min1',
				// },
				param: {},
				gzip: false,
			};
			ws.send(JSON.stringify(params));
		});

		ws.on('message', function message(response) {
			if (response) {
				const msgs = JSON.parse(response);
				if (Array.isArray(msgs.data)) {
					const tickers = msgs.data.slice();
					for (let i = 0; i < tickers.length; i++) {
						const symbol = tickers[i].symbol;
						const timestamp = tickers[i].timestamp;
						const price = tickers[i].lastPrice;
						// поиск по наличию полученного тикера
						// const idx = buffer.map((obj) => obj.ticker).indexOf(symbol);
						const idx = buffer.findIndex(
							(i) => i.ticker === symbol && i.exchange === prefix
						);
						bufferHandler({
							idx,
							symbol,
							timestamp,
							price,
							prefix,
						});
					}
					pingPongHandler({
						prefix,
						ws,
						timestamp: 0,
						count: countPingPong % 50 ? 0 : countPingPong,
					});
				} else if (typeof msgs.data === 'number') {
					countPingPong++;
					// console.log(prefix + ': ' + msgs.channel);
				}
			}
		});

		// setInterval(() => {
		// 	pingPongHandler({
		// 		prefix,
		// 		ws,
		// 		timestamp: 0,
		// 		count: countPingPong % 10 ? 0 : countPingPong,
		// 	});
		// }, 15000);
	}
};

if (isWS) {
	setInterval(() => {
		console.log(
			'+++++++|WS|+++++++ ' + getTimestamps() + ' ++++++++|WS|++++++'
		);
		// console.log('buffer: ' + buffer.length);
		for (let i = 0; i < prefixes.length; i++) {
			printConsole_({
				date: getTimestamps(),
				purcent:
					prefixes[i] === 'BN_f' ||
					prefixes[i] === 'BT_f' ||
					prefixes[i] === 'HB_f' ||
					prefixes[i] === 'KX_f'
						? purcent_alt
						: purcent,
				// purcent,
				prefix: prefixes[i],
				tickers: buffer,
			});
		}
	}, 60000 * period);
}
