import { defineStore, acceptHMRUpdate } from 'pinia';
import { socket } from 'boot/socketio';

import { useDeviceStore } from 'stores/device';
import { useIcloudStore } from 'stores/icloud';
import { useSimulationStore } from 'stores/simulation';
import { useTunneldStore } from 'stores/tunneld';

import type { AppError, ErrorFull, StatusUpdate } from 'components/models';



export const useSocketStore = defineStore('socketStore', {
  state: () => {
    return {
      sockConnected: false as boolean,
      socketID: null as string | null | undefined,
      errorList: [] as ErrorFull[],
      debugLog: true,
    };
  },
  getters: {},
  actions: {
    setSockStatus() {
      this.sockConnected = socket.connected;
      this.socketID = socket.id;
    },
    connect() {
      if (this.debugLog) {
        console.log('Connecting to server...');
      }
      socket.connect();
      this.setSockStatus();
    },
    disconnect() {
      socket.disconnect();
      this.setSockStatus();
    },
    toggleSock() {
      this.setSockStatus();
      if (this.sockConnected) {
        socket.disconnect();
      } else {
        socket.connect();
      }
      this.setSockStatus();
    },
    bindEvents() {
      this.setSockStatus();

      // connect
      socket.on('connect', () => {
        this.setSockStatus();
        socket.emit('message', 'Hello from client', (e: boolean) => {
          if (this.debugLog) {
            console.log('Message delivered: ' + e);
          }
        });
        if (this.debugLog) {
          console.log('Connected to server');
        }
      });

      // disconnect
      socket.on('disconnect', () => {
        this.setSockStatus();
        console.log('Disconnected from server');
      });

      // error
      socket.on('error', (data: ErrorFull) => {
        this.setSockStatus();
        const errorFull = { type: data.type, error: data.error };
        this.errorList.push(errorFull);
        console.error('Error Received: ', data);
      });

      // app_error
      socket.on('app_error', (data: AppError) => {
        this.setSockStatus();
        const errorFull = {
          type: data.type,
          error: data.error,
          message: data.message,
          data: data.data,
        };
        this.errorList.push(errorFull);
        console.error('Error Received: ', data);
      });

      // status
      socket.on('status', (data: StatusUpdate): void => {
        if (this.debugLog) {
          console.log('StatusUpdate received: ', data);
        }
        this.digestUpdate(data);
      });
    },
    requestUpdate(): void {
      socket.emit('request_update', (response: StatusUpdate) => {
        this.digestUpdate(response);
      });
    },
    digestUpdate(data: StatusUpdate): void {
      const deviceStore = useDeviceStore();
      const icloudStore = useIcloudStore();
      const simulationStore = useSimulationStore();
      const tunneldStore = useTunneldStore();
      if (data.simulation_queue) {
        simulationStore.digestQueueUpdate(data.simulation_queue);
      }
      deviceStore.deviceConnected = !!(data.udid && data.tunnel);
      if (data.current_location) {
        simulationStore.digestCurrentLocation(data.current_location);
      }
      tunneldStore.tunnelConnected = !!data.tunnel;
      tunneldStore.tunneldWatcher = data.tunnel_watcher_running;
      if (data.icloud) {
        icloudStore.digestUpdate(data.icloud);
      }
      icloudStore.findMyUpdate = data.fmf_location;

    },
  },
});

if (import.meta.hot) {
  import.meta.hot.accept(acceptHMRUpdate(useSocketStore, import.meta.hot));
}
