import TVoxSDK, { CallSip, CallWebrtc } from '@telenia/tvox-client-sdk';
import { CommonModule } from '@angular/common';
import { Component, OnInit, signal } from '@angular/core';
import {
  FormControl,
  FormsModule,
  ReactiveFormsModule,
  Validators,
} from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
import { MatCardModule } from '@angular/material/card';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
import { MatListModule } from '@angular/material/list';
import { MatTooltipModule } from '@angular/material/tooltip';
import { TVoxService } from 'src/app/tvox-client-sdk.service';

@Component({
  selector: 'call',
  imports: [
    MatCardModule,
    MatListModule,
    FormsModule,
    ReactiveFormsModule,
    MatInputModule,
    MatFormFieldModule,
    MatButtonModule,
    MatTooltipModule,
    CommonModule,
  ],
  templateUrl: './call.component.html',
  styleUrl: './call.component.scss',
  standalone: true,
})
export class CallComponent implements OnInit {
  protected client!: TVoxSDK.Client;
  protected number = new FormControl<string>('', [
    Validators.required,
    Validators.pattern('^[0-9]+$'),
  ]);
  protected call!: TVoxSDK.CallWebrtc | TVoxSDK.CallSip; // prima chiamata
  protected call2!: TVoxSDK.CallWebrtc | TVoxSDK.CallSip; // seconda chiamata (se c'è già una prima in corso)

  protected callInProgress = signal<boolean>(false);
  protected callInProgress2 = signal<boolean>(false);

  protected onHold = false;
  protected muted = false;

  protected onHold2 = false;
  protected muted2 = false;

  protected recording = false;

  protected inboundCall = signal<boolean>(false);
  protected phoneNumber = signal<string | undefined>('');
  protected phoneNumber2 = signal<string | undefined>('');
  protected transferCallEnabled = signal<boolean>(false);

  protected multipleCall = signal<boolean>(false);

  constructor(private tvoxService: TVoxService) {}

  ngOnInit(): void {
    this.client = this.tvoxService.getClient();
    // ricevo l'evento di nuova chiamata
    this.client.phone.on('newcall', (call) => {
      console.log('new call', call);

      if (this.call) {
        this.call2 = call; // se call è già valorizzato e quindi in corso, valorizzo call2
        this.transferCallEnabled.set(true);
        this.phoneNumber2.set(this.number.value ?? undefined);
        this.multipleCall.set(true);
        this.callInProgress2.set(true);
        this.onHold = true;
      } else {
        this.call = call;

        /** Se si desidera impostare dei call data per la chiamata --> */

        if (call instanceof CallWebrtc) {
          // Funziona allo stesso modo per CallSip,
          // ma con la tipizzazione stretta è necessario differenziare le istanze

          // Sottoscrizione al cambio delle feature disponibili per la chiamata in corso
          call.on('change_features', (features: string[]) => {
            // Se nell'array di feature ricevute è presente 'SETCALLDATA', posso usare il metodo
            if (features.includes('SETCALLDATA')) {
              call
                .setCallData('test') // Metodo per impostare i call data di una chiamata
                .then((response: any) => {
                  console.log('setCallData:', response);
                })
                .catch((error: any) => {
                  console.log('setCallData err:', error);
                });
            }
          });
        }
      }

      if (this.call.direction == 'inbound') {
        this.inboundCall.set(true);
        this.phoneNumber.set(this.call.detail.remoteNumber);
      } else {
        this.callInProgress.set(true);
        this.phoneNumber.set(this.number.value ?? undefined);
      }
    });
  }

  callNumber() {
    const phoneNumber = this.number.value ?? '';
    if (this.client.phone.device instanceof TVoxSDK.DeviceWebrtc) {
      // metodo per effettuare una chiamata con dispostivo WEBRTC
      this.client.phone.device
        .dialAudio(phoneNumber)
        .then(() => {})
        .catch((error) => {
          console.error('dialAudio ERROR', error);
        });
    } else {
      // metodo per effettuare una chiamata con dispostivo SIP
      this.client.phone.device
        ?.dial(phoneNumber)
        .then(() => {})
        .catch((error) => {
          console.error('dial ERROR', error);
        });
    }
  }

  answerCall() {
    if (this.call instanceof TVoxSDK.CallWebrtc) {
      this.call.answerAudio().then((res) => {
        // metodo per rispondere ad una chiamata in arrivo con dispostivo WEBRTC
        this.inboundCall.set(false);
        res ? this.callInProgress.set(true) : null;
      });
    } else {
      this.call.answer().then((res) => {
        // metodo per rispondere ad una chiamata in arrivo con dispostivo SIP
        this.inboundCall.set(false);
        res ? this.callInProgress.set(true) : null;
      });
    }
  }

  holdCall(callNumber: number) {
    // callNumber mi serve per distinguere su quale chiamata compiere l'azione
    if (callNumber == 1) {
      this.call
        .hold() // metodo per mettere in hold la chiamata
        .then((res) => {
          res ? (this.onHold = true) : null;
          console.log('call hold DONE');
        })
        .catch((error) => {
          console.error('call hold ERROR', error);
        });
    } else {
      this.call2
        .hold() // metodo per mettere in hold la chiamata
        .then((res) => {
          res ? (this.onHold2 = true) : null;
          console.log('call hold DONE');
        })
        .catch((error) => {
          console.error('call hold ERROR', error);
        });
    }
  }

  unholdCall(callNumber: number) {
    if (callNumber == 1) {
      this.call
        .unhold() // metodo per togliere da hold la chiamata
        .then((res) => {
          res ? (this.onHold = false) : null;
          console.log('call unhold DONE');
        })
        .catch((error) => {
          console.error('call unhold ERROR', error);
        });
    } else {
      this.call2
        .unhold() // metodo per togliere da hold la chiamata
        .then((res) => {
          res ? (this.onHold2 = false) : null;
          console.log('call unhold DONE');
        })
        .catch((error) => {
          console.error('call unhold ERROR', error);
        });
    }
  }

  muteCall(callNumber: number) {
    if (this.call instanceof TVoxSDK.CallWebrtc) {
      if (callNumber == 1) {
        this.call
          .mute({ audio: true }) // metodo per disabilitare il microfono
          .then((res) => {
            res ? (this.muted = true) : null;
            console.log('call mute DONE');
          })
          .catch((error) => {
            console.error('call mute ERROR', error);
          });
      } else {
        if (this.call2 instanceof TVoxSDK.CallWebrtc) {
          this.call2
            .mute({ audio: true }) // metodo per disabilitare il microfono
            .then((res) => {
              res ? (this.muted2 = true) : null;
              console.log('call mute DONE');
            })
            .catch((error) => {
              console.error('call mute ERROR', error);
            });
        }
      }
    }
  }

  unmuteCall(callNumber: number) {
    if (this.call instanceof TVoxSDK.CallWebrtc) {
      if (callNumber == 1) {
        this.call
          .unmute({ audio: true }) // metodo per riabilitare il microfono
          .then((res) => {
            res ? (this.muted = false) : null;
            console.log('call unmute DONE');
          })
          .catch((error) => {
            console.error('call unmute ERROR', error);
          });
      } else {
        if (this.call2 instanceof TVoxSDK.CallWebrtc) {
          this.call2
            .unmute({ audio: true }) // metodo per riabilitare il microfono
            .then((res) => {
              res ? (this.muted2 = false) : null;
              console.log('call unmute DONE');
            })
            .catch((error) => {
              console.error('call unmute ERROR', error);
            });
        }
      }
    }
  }

  transferCall() {
    if (this.call2 instanceof TVoxSDK.CallWebrtc) {
      this.call2
        .transferToCall(this.call) // metodo per trasferire la chiamta con dispositivo WEBRTC
        .then((res) => {
          console.log('transferToCall DONE');
          this.callInProgress.set(false);
          this.callInProgress2.set(false);
        })
        .catch((error) => {
          console.error('transferToCall ERROR', error);
        });
    }
  }

  dropCall(callNumber: number) {
    if (callNumber == 1) {
      this.call
        .terminate() // metodo per abbattere la chiamata
        .then((res) => {
          res ? this.callInProgress.set(false) : null;
          this.inboundCall ? this.inboundCall.set(false) : null;
          (this.call as any) = undefined;
          console.log('call terminate DONE');
        })
        .catch((error) => {
          console.error('call terminate ERROR', error);
        });
    } else {
      this.call2
        .terminate() // metodo per abbattere la chiamata
        .then((res) => {
          res ? this.callInProgress2.set(false) : null;
          (this.call2 as any) = undefined;
          console.log('call terminate DONE');
        })
        .catch((error) => {
          console.error('call terminate ERROR', error);
        });
    }
  }

  startRecord() {
    // metodo per registrare una chiamata
    this.call.recording
      .startRecord()
      .then((res) => {
        console.log('startRecord DONE', res);
        this.recording = true;
      })
      .catch((error) => {
        console.error('startRecord ERROR', error);
      });
  }

  stopRecord() {
    // metodo per terminare la regisrazione di una chiamata
    this.call.recording
      .stopRecord()
      .then((res) => {
        console.log('stopRecord DONE', res);
        this.recording = false;
      })
      .catch((error) => {
        console.error('stopRecord ERROR', error);
      });
  }
}
