<script>
import { ref, computed } from 'vue';
import { DateTime } from '@silane/datetime';

import { inject, keys as injectionKeys } from '../../injection';
import { readTextFile, downloadFile } from '../../common/utils.js';
import { toJSONObject, fromJSONObject } from '../../common/exported-data.js';
import { useDataimporterexporter } from '../../composables/dataimporterexporter';


export default {
  name: 'PageMasterImportExport',
  setup() {
    const notification = inject(injectionKeys.notification);
    const handleError = inject(injectionKeys.errorHandler).handleErrorAsync;

    const dataimporterexporter = useDataimporterexporter(
      inject(injectionKeys.database),
      inject(injectionKeys.timeLabelStore),
      inject(injectionKeys.resourceStore),
    );

    const exportedDataCopied = ref(false);
    const importData = ref('');

    const exportedData = computed(
      () => dataimporterexporter.exportedData.value ? JSON.stringify(toJSONObject(
        dataimporterexporter.exportedData.value
      )) : ''
    );

    const load = handleError(async () => {
      await dataimporterexporter.load();
    });
    load();

    const importFromText = handleError(async text => {
      let data;
      try {
        data = JSON.parse(text);
      } catch(e) {
        if(e instanceof SyntaxError) {
          notification.add('error', 'インポートに失敗しました。不正な形式です。');
          return;
        }
        throw e;
      }
      try {
        data = fromJSONObject(data);
      } catch {
        notification.add('error', 'インポートに失敗しました。不正な形式です。');
        return;
      }
      await dataimporterexporter.import(data);
      notification.add('info', 'インポートしました。');
    });

    async function importFromFile(file) {
      const text = await readTextFile(file);
      await importFromText(text);
    }

    function exportToFile() {
      const file = new File(
        [exportedData.value],
        `zkan-exported-${DateTime.now().strftime('%Y%m%d_%H%M')}.json`,
        { type: 'application/json' }
      );
      downloadFile(file);
    }

    async function copyExportedDataToClipboard(text) {
      exportedDataCopied.value = false;
      await globalThis.navigator.clipboard.writeText(text);
      exportedDataCopied.value = true;
    }

    return {
      exportedData, exportedDataCopied, importData, exportToFile,
      importFromFile, importFromText, copyExportedDataToClipboard,
    };
  },
}
</script>

<template>
<h1>データインポート・エクスポート</h1>
<section>
  <h1>エクスポート</h1>
  <button
    type="button" @click="exportToFile()"
  >ファイルにエクスポート</button>
  <p>
    テキストとしてエクスポート:
    <input readonly="readonly" :value="exportedData" />
    <button
      type="button" @click="copyExportedDataToClipboard(exportedData)"
    >コピー</button>
    <transition name="copied">
      <span v-if="exportedDataCopied" class="copied">
        コピーしました
      </span>
    </transition>
  </p>
</section>
<section>
  <h1>インポート</h1>
  <p>インポートすると現在のデータは全て上書きされます。注意してください。</p>
  <p>
    <label>
      ファイルからインポート:
      <input type="file" accept=".json" @change="
        importFromFile($event.target.files[0]);
        $event.target.value = '';
      " />
    </label>
  </p>
  <p>
    テキストからインポート:
    <input v-model="importData" />
    <button
      type="button" @click="importFromText(importData)"
    >インポート</button>
  </p>
</section>
</template>

<style scoped>
@keyframes bounce-in {
  0% {
    transform: scale(0);
  }
  50% {
    transform: scale(1.25);
  }
  100% {
    transform: scale(1);
  }
}
.copied {
  display: inline-block;  
}
.copied-enter-active {
  animation: 0.5s bounce-in;
}
</style>
