/** @format */

import SIPml from 'ecmascript-webrtc-sipml';
import { toast } from 'react-hot-toast';
import outcomingringTone from '../sounds/ringtone.wav';
import waitRingTone from '../sounds/ringbacktone.wav';
import pickSound from '../sounds/dtmf.wav';

export class BoxDialer {
	sTransferNumber;
	oRingTone;
	oRingbackTone;
	oSipStack;
	oSipSessionRegister;
	oSipSessionCall;
	oSipSessionTransferCall;
	videoRemote;
	videoLocal;
	audioRemote;
	bFullScreen = false;
	oNotifICall;
	bDisableVideo = false;
	viewVideoLocal;
	viewVideoRemote;
	viewLocalScreencast; // <video> (webrtc) or <div> (webrtc4all)
	oConfigCall;
	oReadyStateTimer;
	ringtone;
	ringbacktone;
	sipState;
	soundBool;
	onSipStateChange = {};
	callEvetsBoxDialer;
	timer = {
		time: 0,
		type: null,
	};

	testTimer;

	constructor() {
		this.played = false;
		document.body.addEventListener('click', () => {
			this.played = true;
		});
		this.videoRemote = document.createElement('video');
		this.videoLocal = document.createElement('video');
		this.audioRemote = document.createElement('audio');

		this.audioRemote.autoplay = true;

		document.body.appendChild(this.videoRemote);
		document.body.appendChild(this.videoLocal);
		document.body.appendChild(this.audioRemote);

		this.ringtone = new Audio(outcomingringTone);
		this.waitRingTone = new Audio(waitRingTone);
		this.pickSound = new Audio(pickSound);

		this.ringtone.loop = true;
		this.waitRingTone.loop = true;

		this.callEvetsBoxDialer = {
			callHold: false,
			callMute: null,
		};
		this.oConfigCall = {
			audio_remote: this.audioRemote,
			video_local: this.viewVideoLocal, //this.viewVideoLocal
			video_remote: this.viewVideoRemote, // this.viewVideoRemote
			screencast_window_id: 0x00000000, // entire desktop
			bandwidth: { audio: undefined, video: undefined },

			video_size: {
				minWidth: undefined,
				minHeight: undefined,
				maxWidth: undefined,
				maxHeight: undefined,
			},
			events_listener: {
				events: '*',
				listener: (event) => this.onSessionEvent({ type: 'call', event }),
			},
			sip_caps: [
				{ name: '+g.oma.sip-im' },
				{ name: 'language', value: '"en,fr"' },
			],
		};
	}

	startTimer() {
		console.log('start timer');
		this.testTimer = setInterval(() => {
			this.timer.time = this.timer.time + 1;
			this.onSipStateChange.setDndTimer(this.timer.time);
		}, 1000);
	}
	stopTimer() {
		clearInterval(this.testTimer);
		this.timer.time = 0;
		this.onSipStateChange.setDndTimer(this.timer.time);
	}

	onSoundType({ type, bool }) {
		console.log(
			this.ringtone,
			'sound',
			{ type, bool },
			`body clicked: ${this.played}`,
		);

		if (this.played) {
			switch (type) {
				case 'ring':
					if (bool) {
						this.ringtone.pause();
						this.ringtone.remove();
						console.log(this.ringtone, 'sound ringtone');

						this.ringtone.play();
					} else {
						this.ringtone.pause();
						this.ringtone.remove();
					}
					break;
				case 'wait':
					if (bool) {
						this.waitRingTone.pause();
						this.waitRingTone.remove();
						console.log(this.waitRingTone, 'sound waitRingTone');

						this.waitRingTone.play();
					} else {
						this.waitRingTone.pause();
						this.waitRingTone.remove();
					}
					break;
				case 'pick':
					if (bool) {
						this.pickSound.remove();
						this.pickSound.pause();

						this.pickSound.play();
					} else {
						this.pickSound.pause();
						this.pickSound.remove();
					}
					break;
				default:
					console.error('onSoundType: Such a sound does not exist');
					break;
			}
		}
	}

	sipRegister = ({ number, secret, wsurl }) => {
		try {
			Notification.requestPermission();

			SIPml.setDebugLevel(
				window.localStorage &&
					window.localStorage.getItem('org.doubango.expert.disable_debug') ===
						'true'
					? 'error'
					: 'info',
			);

			// create SIP stack
			this.oSipStack = new SIPml.Stack({
				realm: wsurl, // 'cld.alovoice.uz:61040',
				impi: number, //'3003',
				impu: `sip:${number}@${wsurl}`, //'sip:3003@cld.alovoice.uz:61040',
				password: secret, //'944ad5',
				display_name: number, //'3003',
				websocket_proxy_url: `wss://${wsurl}/ws`, //'wss://cld.alovoice.uz:61040/ws',
				// outbound_proxy_url: '', //(window.localStorage ? window.localStorage.getItem('org.doubango.expert.sip_outboundproxy_url') : null),
				ice_servers: [{ url: 'stun:stun.l.google.com:19302' }], //(window.localStorage ? window.localStorage.getItem('org.doubango.expert.ice_servers') : null),
				enable_rtcweb_breaker: true, //(window.localStorage ? window.localStorage.getItem('org.doubango.expert.enable_rtcweb_breaker') == "true" : false),
				events_listener: {
					events: '*',
					listener: (event) => this.onSessionEvent({ type: 'stack', event }),
				},
				enable_early_ims: true, //(window.localStorage ? window.localStorage.getItem('org.doubango.expert.disable_early_ims') != "true" : true), // Must be true unless you're using a real IMS network
				enable_media_stream_cache: true, //(window.localStorage ? window.localStorage.getItem('org.doubango.expert.enable_media_caching') == "true" : false),
				//bandwidth: (window.localStorage ? tsk_string_to_object(window.localStorage.getItem('org.doubango.expert.bandwidth')) : null), // could be redefined a session-level
				//video_size: (window.localStorage ? tsk_string_to_object(window.localStorage.getItem('org.doubango.expert.video_size')) : null), // could be redefined a session-level
				sip_headers: [
					{
						name: 'User-Agent',
						value: 'Alovoice-client/v1.0-2023.08.08',
					},
					{ name: 'Organization', value: 'Technounit' },
				],
			});

			if (this.oSipStack.start() !== 0) {
				console.log('<b>Failed to start the SIP stack</b>');
			} else return;
		} catch (e) {
			console.log('<b>2:' + e + '</b>');
		}
	};

	register() {
		if (this.oSipSessionRegister) this.oSipSessionRegister.unregister();
		this.oSipSessionRegister = this.oSipStack.newSession('register', {
			expires: 200,
			events_listener: {
				events: '*',
				listener: (event) => {
					this.onSessionEvent({ type: 'register', event });
					return event;
				},
			},
		});
		this.oSipSessionRegister.register();
	}

	callBxMethods({ bxMethodName, bxFuncParams, callback }) {
		if (window.BX24 && window.BX24.placement) {
			window?.BX24.placement.call(bxMethodName, bxFuncParams, callback);
		} else if (window.alovoicePhone && window.alovoicePhone.callMethods) {
			window.alovoicePhone.callMethods[bxMethodName](bxFuncParams, callback);
		}
	}

	setGuiPhoneState({ stateCode, funcName, funcParam }) {
		if (window?.alovoice_wsphone) {
			let uiState = '';

			switch (stateCode) {
				case 'i_new_call':
					uiState = 'incoming';
					break;
				case 'connected':
					uiState = 'connected';
					break;
				default:
					break;
			}

			this.callBxMethods({
				bxMethodName: 'CallCardSetUiState',
				bxFuncParams: { uiState },
				callback: (e) => {
					console.log(e, `CallCardSetUiState method done ${e}`);
				},
			});
		} else {
			if (this.onSipStateChange[funcName] !== 'undefined') {
				this.onSipStateChange[funcName](funcParam);
			}
		}
	}

	bxLog(...datas) {
		console.log(`%c BXLOG:`, datas, 'background-color: red;');
	}

	onSessionEvent({ type, event }) {
		this.sipState = type + '_' + event?.type;
		console.log('---onSessionEvent EVENT [' + this.sipState + ']', event);

		switch (this.sipState) {
			case 'register_stopping':
			case 'register_stoped':
			case 'register_failed_to_start':
			case 'register_failed_to_stop':
				this.oSipStack = null;
				this.oSipSessionRegister = null;
				this.oSipSessionCall = null;
				break;

			case 'register_terminated':
				// оторвался
				break;

			case 'register_connected':
				this.onSipStateChange.dynamicValue('connected');
				break;

			case 'register_connecting':
				this.onSipStateChange.dynamicValue('pending');
				break;

			case 'stack_started':
				this.register();
				break;

			case 'call_connecting':
				this.setGuiPhoneState({
					funcName: 'modalState',
					funcParam: {
						bool: true,
						callType: 'outcoming',
						callAnswerType: null,
					},
				});
				break;

			case 'call_connected':
				// QORA EKRANDA ULANYAPTI.. SOZINI VAHTGA OZGARTIRISH KERE ( SEKKUNDAMER )
				break;

			case 'hangup_terminating':
				// QORA EKRANNI OCHIRISH KERE
				this.setGuiPhoneState({
					funcName: 'modalState',

					funcParam: {
						bool: false,
						callType: 'outcoming',
						callAnswerType: null,
					},
				});
				break;

			case 'call_terminated':
				console.log('%c call_terminated', 'background-color: yellow;');
				this.onSoundType({ type: 'ring', bool: false });

				this.setGuiPhoneState({
					funcName: 'modalState',
					funcParam: {
						bool: false,
						callType: 'outcoming',
						callAnswerType: null,
						callFromName: null,
					},
				});

				break;

			case 'stack_i_new_call':
				this.oSipSessionCall = event.newSession;
				this.oSipSessionCall.setConfiguration(this.oConfigCall);
				this.onSoundType({ type: 'ring', bool: true });
				this.setGuiPhoneState({
					funcName: 'modalState',
					funcParam: {
						bool: true,
						callType: '',
						callAnswerType: null,
						callFromName: event?.o_event?.o_session?.o_uri_from?.s_user_name,
					},
				});
				break;

			case 'stack_stopped':
				this.register();
				break;

			default:
				break;
		}
	}

	selectUser() {
		BX.Runtime.loadExtension('ui.entity-selector').then((exports) => {
			const { Dialog, TagSelector } = exports;

			const dialog = new BX.UI.EntitySelector.Dialog({
				// targetNode: button,
				enableSearch: true,
				multiple: false,
				context: 'MY_MODULE_CONTEXT',
				entities: [
					{
						id: 'user', // пользователи
						options: { selectFields: ['ufPhoneInner'] },
					},
					{
						id: 'department', // структура компании: выбор только пользователей
					},
				],
				events: {
					'_Item:onSelect': (event) => {
						const { item } = event.getData();
						const dialog = event.getTarget();
						const selectedItems = dialog.getSelectedItems();

						if (item.customData.get('ufPhoneInner')) {
							this.transferButtonClick(item.customData.get('ufPhoneInner'));
						}
					},
					get 'Item:onSelect'() {
						return this['_Item:onSelect'];
					},
					set 'Item:onSelect'(value) {
						this['_Item:onSelect'] = value;
					},
				},
			});
			dialog.show();
		});
	}

	// call_connected;
	setSipStateChangeCallback(callback, funcName) {
		this.onSipStateChange[funcName] = callback.bind(this);
	}

	sipHangUp() {
		console.log('sipHangUp');
	}
	sipUnRegister() {
		console.log('sipUnRegister');
	}
	sipTransfer() {
		console.log('sipTransfer');
	}

	initialized(phoneNumber, phone) {
		// if (phoneNumber == phone) {
		// toast.error('Please enter another number');
		// return;
		// }
		console.log('initialized argument', phoneNumber);
		this.callBxMethods({
			bxMethodName: 'CallCardSetUiState',
			bxFuncParams: { uiState: 'connectingOutgoing' },
			callback: (e) => {
				console.log(e, `CallCardSetUiState method done ${e}`);
			},
		});

		let phoneNumberString = phoneNumber.toString();
		if (phoneNumberString.length) {
			this.oSipSessionCall = this.oSipStack.newSession(
				'call-audio',
				this.oConfigCall,
			);
			this.oSipSessionCall.call(phoneNumberString);
		} else {
			toast.error('Do not correct number', {
				style: {
					zIndex: '99999999999999999',
				},
			});
		}
	}
	stopCall() {
		this.onSoundType({ type: 'ring', bool: false });
		this.onSipStateChange.modalState({
			bool: false,
			callType: 'answered',
			callAnswerType: 'oncoming',
			callFromName: null,
		});
		if (this.oSipSessionCall) {
			this.oSipSessionCall.hangup({
				events_listener: {
					events: '*',
					listener: (event) => this.onSessionEvent({ type: 'hangup', event }),
				},
			});
		}
	}

	skipButtonClick() {
		this.onSoundType({ type: 'ring', bool: false });
		this.stopCall();
	}

	answerButtonClick() {
		this.onSipStateChange.modalState({
			bool: true,
			callType: 'answered',
			callAnswerType: 'oncoming',
		});
		this.oSipSessionCall.accept(this.oConfigCall);
		this.onSoundType({ type: 'ring', bool: false });
	}
	sipSendDTMF(c) {
		if (this.oSipSessionCall && c) {
			this.oSipSessionCall.dtmf(c);
		}
	}

	addCommentButtonClick() {
		console.log('addCommentButtonClick');
	}
	muteButtonClick() {
		console.log(this.callEvetsBoxDialer, 'dsadfdssad INSET');

		this.callEvetsBoxDialer = {
			...this.callEvetsBoxDialer,
			callMute: !this.oSipSessionCall.bMute,
		};

		this.oSipSessionCall.mute('audio', this.callEvetsBoxDialer.callMute);
		this.oSipSessionCall.bMute = this.callEvetsBoxDialer.callMute;
		this.onSipStateChange.setCallEvents(this.callEvetsBoxDialer);
	}
	holdButtonClick() {
		if (this.callEvetsBoxDialer.callHold) {
			this.oSipSessionCall.resume();
			this.callEvetsBoxDialer = {
				...this.callEvetsBoxDialer,
				callHold: false,
			};
		} else {
			this.oSipSessionCall.hold();
			this.callEvetsBoxDialer = {
				...this.callEvetsBoxDialer,
				callHold: true,
			};
		}

		this.oSipSessionCall.bHeld = this.callHold;
		this.onSipStateChange.setCallEvents(this.callEvetsBoxDialer);
	}
	closeButtonClick() {
		console.log('closeButtonClick');
	}
	transferButtonClick(number) {
		if (this.oSipSessionCall) {
			if (this.oSipSessionCall.transfer(number) != 0) {
				toast.error('Call transfer failed');
				return;
			}
			toast('Call transfered');
			this.onSipStateChange.modalState({
				bool: false,
				callType: 'answered',
				callAnswerType: 'oncoming',
				callFromName: null,
			});
		}
	}
	cancelTransferButtonClick() {
		console.log('cancelTransferButtonClick');
	}
	completeTransferButtonClick() {
		console.log('completeTransferButtonClick');
	}
	nextButtonClick() {
		console.log('nextButtonClick');
	}

	entityChanged() {
		console.log('entityChanged');
	}
	qualityMeterClick() {
		console.log('qualityMeterClick');
	}
	dialpadButtonClick() {
		console.log('dialpadButtonClick');
	}
	notifyAdminButtonClick() {
		console.log('notifyAdminButtonClick');
	}
}