<template>
  <h2 class="tool-title">Hash</h2>

  <hr class="mt-5 mb-5" />

  <div class="input-group">
    <label for="data">Data</label>
    <textarea id="data" v-model="toolData.data" v-on:change="result"></textarea>
  </div>

  <div class="input-group mt-3">
    <label for="algorithm">Algorithm</label>
    <div>
      <select id="algorithm" v-model="toolData.algorithm" v-on:change="result">
        <option value="md5">MD5</option>
        <option value="sha1">SHA-1</option>
        <option value="sha256">SHA-256</option>
        <option value="sha512">SHA-512</option>
      </select>
    </div>
  </div>

  <div class="input-group mt-3">
    <label for="outputFormat">Output format</label>
    <div>
      <select id="outputFormat" v-model="toolData.outputFormat" v-on:change="result">
        <option value="hex">Hex</option>
        <option value="binary">Binary</option>
        <option value="base64">Base64</option>
        <option value="base64url">Base64 URL-safe</option>
      </select>
    </div>
  </div>

  <hr class="mt-5 mb-5" />

  <div class="input-group">
    <label for="result">Result</label>
    <input
      id="result"
      class="input"
      :value="toolResult"
      type="text"
      readonly
    >
  </div>
</template>

<script>
export default {
  data() {
    return {
      toolData: {
        data: '',
        algorithm: 'sha256',
        outputFormat: 'hex',
      },
      toolResult: '',
    };
  },
  methods: {
    async result() {
      const encoder = new TextEncoder();
      const dataBuffer = encoder.encode(this.toolData.data);

      let hashBuffer;
      switch (this.toolData.algorithm) {
        case 'md5':
          hashBuffer = await crypto.subtle.digest('MD5', dataBuffer);
          break;
        case 'sha1':
          hashBuffer = await window.crypto.subtle.digest('SHA-1', dataBuffer);
          break;
        case 'sha256':
          hashBuffer = await window.crypto.subtle.digest('SHA-256', dataBuffer);
          break;
        case 'sha512':
          hashBuffer = await window.crypto.subtle.digest('SHA-512', dataBuffer);
          break;
        default:
          throw new Error(`Unsupported algorithm: ${this.toolData.algorithm}`);
      }

      let hash;
      switch (this.toolData.outputFormat) {
        case 'hex':
          hash = this.arrayBufferToHex(hashBuffer);
          break;
        case 'binary':
          hash = this.arrayBufferToBinary(hashBuffer);
          break;
        case 'base64':
          hash = btoa(String.fromCharCode(...new Uint8Array(hashBuffer)));
          break;
        case 'base64url':
          hash = btoa(String.fromCharCode(...new Uint8Array(hashBuffer)))
            .replace(/\+/g, '-')
            .replace(/\//g, '_')
            .replace(/=+$/, '');
          break;
        default:
          throw new Error(`Unsupported output format: ${this.toolData.outputFormat}`);
      }

      this.toolResult = hash;
    },
    arrayBufferToHex(buffer) {
      return [...new Uint8Array(buffer)]
        .map((b) => b.toString(16).padStart(2, '0'))
        .join('');
    },
    arrayBufferToBinary(buffer) {
      return [...new Uint8Array(buffer)]
        .map((b) => b.toString(2).padStart(8, '0'))
        .join('');
    },
  },
};
</script>

<style lang="scss"></style>