import { Injectable } from '@angular/core';
import { v4 as uuidv4 } from 'uuid'
import { BackgroundService } from '../background.service';

export interface wss{

  url: string,
  type: 'reflect' | 'emit'
  header: {
    id: string
    bluePrint: string,
    jwt: string
  }

}

@Injectable({
  providedIn: 'root'
})
export class SynchroService {
	[x: string]: any;

	private connection!: WebSocket;
  private id: string = uuidv4();
  public conected = false
  private url: string = ''
  callback = function(){}
  private _connected = false;
  private BackgroundService = new BackgroundService()
  private callBacks: {
    type: 'Offline' | 'Online'
    funx: Function
  }[] = []

	constructor(){}

  get connected() {
    return this._connected
  }

  setUrl() {

    let header ={
      id:'1234',
      bluePrint: '12312123',
      jwt: uuidv4()
    }
    
    let wss: wss ={
      header,
      url: 'wss://synchro-server.herokuapp.com/ws/some_url/',
      type: 'reflect'
    }

    this.url = `${wss.url}${wss.header.id}/${wss.header.jwt}/${wss.header.bluePrint}/${this.id}/`
  }

  registerCallback(type: 'Offline' | 'Online', funx: Function) {
    this.callBacks.push({
      type,
      funx
    })
  }

	connect() {

		this.connection  = new WebSocket(this.url);
		// bind function
		this.connection.onopen = this.onopen;
		this.connection.onmessage = this.onmessage;
		this.connection.onclose = this.onclose;
		this.connection.onerror = this.onerror;
	}

	private onopen = () =>{
    
    this.BackgroundService.online()
    
    this.callBacks.forEach((e)=>{
      if(e.type == 'Online') {
        e.funx()
      }
    })

    console.log('open ======================= welcome to socket server')
    this._connected = true

	}

  public $send(object: any) {

    let message =  {
      message: '{"person.adress.country":"1Angola"}',
      username: '',
      idConnection: this.id
    }

    let sendData = JSON.stringify(Object.assign({}, message));

    this.connection.send(sendData);
  }

	private onmessage = async (event: any)=> {
    this.callback()
	}

	private onclose=(event:any)=> {
		setTimeout(() => {
			if (event.wasClean) {
				console.log(`[close] Connection closed cleanly, code=${event.code} reason=${event.reason}`);
			} else {
				// e.g. server process killed or network down
				// event.code is usually 1006 in this case
				console.log('[close] Connection died');
        console.log('Reconnect')

        this.BackgroundService.offline();

        this.callBacks.forEach((e)=>{
          if(e.type == 'Offline') {
            e.funx()
          }
        })

        // status
        this._connected = false
        // reconnect
        this.connect()
        
			}
		}, 100);
	}

  private onerror=(event: any)=>{
		console.log(`[error] ${event.message}`);
	}
}


export const connection = new SynchroService()
connection.setUrl()
connection.connect()

