import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Injectable } from '@angular/core';
import * as _sodium from 'libsodium-wrappers';
import { map } from 'rxjs';
import { apiTemp, public_key, secret_key } from 'src/environments/environment';

@Injectable({
  providedIn: 'root'
})
export class EncService {

  constructor(
    private http: HttpClient
  ) { }

  shortEncrypt(encrypted: string){
    return this.postQuery("short-encryption", {string: encrypted}).pipe(map((data: any) => data));
  }

  encriptar(valor: string) {
    return (async() => {
      await _sodium.ready;
      const sodium = _sodium;
      var nonce = sodium.randombytes_buf(sodium.crypto_box_NONCEBYTES);
    
      var encoded = sodium.crypto_box_easy(
        valor,
        nonce,
        this.stringToUT8(public_key),
        this.stringToUT8(secret_key)
      );
  
      var data_json = JSON.stringify(encoded);
      var nonce_json = JSON.stringify(nonce);
  
      let data_base64 = window.btoa(data_json);
      let nonce_base64 = window.btoa(nonce_json);
  
      let enc = window.btoa(data_base64 + '|' + nonce_base64);
  
      return enc;
    })();
  }

  /* encriptar(valor: string) {
    var nonce = _sodium.randombytes_buf(_sodium.crypto_box_NONCEBYTES);
    
    var encoded = _sodium.crypto_box_easy(
      valor,
      nonce,
      this.stringToUT8(public_key),
      this.stringToUT8(secret_key)
    );

    var data_json = JSON.stringify(encoded);
    var nonce_json = JSON.stringify(nonce);

    let data_base64 = window.btoa(data_json);
    let nonce_base64 = window.btoa(nonce_json);

    let enc = window.btoa(data_base64 + '|' + nonce_base64);

    return enc;
    
  } */

   desencriptar(valor: string) {
    return (async() => {
      await _sodium.ready;
      const sodium = _sodium;

      let valor_base64 = window.atob(valor);
      
      let arrEnc = valor_base64.split('|');
      
      let nonce = window.atob(arrEnc[1]);
      let nonce_arr = JSON.parse(nonce);
      if (typeof nonce_arr == "object") nonce_arr = Object.values(nonce_arr)
      let nonce_final = Uint8Array.from(nonce_arr);
      
      let enc = window.atob(arrEnc[0]);
      let enc_arr = JSON.parse(enc);    
      if (typeof nonce_arr == "object") enc_arr = Object.values(enc_arr)
      let enc_final = Uint8Array.from(enc_arr);
      
      
      var decoded = sodium.crypto_box_open_easy(
        enc_final,
        nonce_final,
        this.stringToUT8(public_key),
        this.stringToUT8(secret_key)
      );
      
      //let dec = this.UT8ToString(decoded);
      let decoder = new TextDecoder();
      let dec = decoder.decode(decoded);

      return dec;
    })();
  }

  /* desencriptar(valor: string) {
    return (async() => {
      await _sodium.ready;
      const sodium = _sodium;

      let valor_base64 = window.atob(valor);
      let arrEnc = valor_base64.split('|');
      
      let nonce = window.atob(arrEnc[1]);
      let nonce_arr = JSON.parse(nonce);
      if (typeof nonce_arr == "object") nonce_arr = Object.values(nonce_arr)
      let nonce_final = Uint8Array.from(nonce_arr);
      
      let enc = window.atob(arrEnc[0]);
      let enc_arr = JSON.parse(enc);    
      if (typeof nonce_arr == "object") enc_arr = Object.values(enc_arr)
      let enc_final = Uint8Array.from(enc_arr);
      
      
      var decoded = sodium.crypto_box_open_easy(
        enc_final,
        nonce_final,
        this.stringToUT8(public_key),
        this.stringToUT8(secret_key)
      );
      
      let dec = this.UT8ToString(decoded);

      return dec;
    })();
  } */

  /* desencriptar(valor: string) {
    return (async() => {
      await _sodium.ready;
      const sodium = _sodium;

      let valor_base64 = window.atob(valor);
      let arrEnc = valor_base64.split('|');

      let nonce = window.atob(arrEnc[1]);
      let nonce_arr = JSON.parse(nonce);
      if(typeof nonce_arr == "object") nonce_arr = Object.values(nonce_arr);
      let nonce_final = new Uint8Array(nonce_arr);

      let enc = window.atob(arrEnc[0]);
      let enc_arr = JSON.parse(enc);    
      if(typeof enc_arr == "object") enc_arr = Object.values(enc_arr);
      
      let enc_final = new Uint8Array(enc_arr);
      
      var decoded = sodium.crypto_box_open_easy(
        enc_final,
        nonce_final,
        this.stringToUT8(public_key),
        this.stringToUT8(secret_key)
      );
      
      let decoder = new TextDecoder('utf-8');
      let dec = decoder.decode(decoded);

      return dec;
    })();
  } */

  private stringToUT8(key: string): Uint8Array {
    let pk_dec = window.atob(key);
    let arr_enc = [];

    for (let index = 0; index < pk_dec.length; index++) {
      arr_enc.push(pk_dec.charCodeAt(index));
    }

    var arr = new Uint8Array(arr_enc);
    return arr;
  }

  private UT8ToString(arr: Uint8Array): string {
    let dec: string = '';
    arr.forEach((element) => {
      dec += String.fromCharCode(element);
    });
    return dec;
  }

  postQuery(query: string, body: any){
    const URL = `${apiTemp}${query}`;
    return this.http.post(URL, body);
  }
}
