<template>
  <div v-if="visible" class="dialog-overlay z-[60]">
    <div class="dialog relative">
      <div class="text-lg text-center font-light relative z-50">
        <div
          id="ViewHeading"
          class="text-center font-bold absolute top-0 left-0 right-0 px-4 py-0.5 bg-black/50 text-white leading-none"
        >
          Camera or Other?
        </div>
        <div
          class="text-lg text-center px-2 py-0.5 leading-none absolute right-0 top-0 text-white"
          @click="close()"
        >
          <fa icon="xmark" class="w-[1em]"></fa>
        </div>
      </div>

      <div>
        <div class="text-center mt-8">
          <div class>
            <fa
              icon="camera"
              class="bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-2 py-2 rounded-md"
              @click="openPhotoDialog()"
            />
          </div>
          <div class="mt-4">
            <input type="file" @change="uploadImageFile" />
          </div>
          <div class="mt-4">
            <span class="mt-2">
              ... or paste a URL:
              <input type="text" v-model="imageUrl" class="border-2" />
            </span>
            <span class="ml-2">
              <fa
                v-if="imageUrl"
                icon="check"
                class="bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-2 py-2 rounded-md cursor-pointer"
                @click="acceptUrl"
              />
              <!-- so that there's no shifting when it becomes visible -->
              <fa v-else icon="check" class="text-white bg-white px-2 py-2" />
            </span>
          </div>
        </div>
      </div>
    </div>
  </div>
  <PhotoDialog ref="photoDialog" />
</template>

<script lang="ts">
import axios from "axios";
import { ref } from "vue";
import { Component, Vue } from "vue-facing-decorator";

import PhotoDialog from "@/components/PhotoDialog.vue";
import { NotificationIface } from "@/constants/app";

const inputImageFileNameRef = ref<Blob>();

@Component({
  components: { PhotoDialog },
})
export default class ImageMethodDialog extends Vue {
  $notify!: (notification: NotificationIface, timeout?: number) => void;

  claimType: string;
  crop: boolean = false;
  imageCallback: (imageUrl?: string) => void = () => {};
  imageUrl?: string;
  visible = false;

  open(setImageFn: (arg: string) => void, claimType: string, crop?: boolean) {
    this.claimType = claimType;
    this.crop = !!crop;
    this.imageCallback = setImageFn;

    this.visible = true;
  }

  openPhotoDialog(blob?: Blob, fileName?: string) {
    this.visible = false;

    (this.$refs.photoDialog as PhotoDialog).open(
      this.imageCallback,
      this.claimType,
      this.crop,
      blob,
      fileName,
    );
  }

  async uploadImageFile(event: Event) {
    this.visible = false;

    inputImageFileNameRef.value = event.target.files[0];
    // https://developer.mozilla.org/en-US/docs/Web/API/File
    // ... plus it has a `type` property from my testing
    const file = inputImageFileNameRef.value;
    if (file != null) {
      const reader = new FileReader();
      reader.onload = async (e) => {
        const data = e.target?.result as ArrayBuffer;
        if (data) {
          const blob = new Blob([new Uint8Array(data)], {
            type: file.type,
          });
          this.openPhotoDialog(blob, file.name as string);
        }
      };
      reader.readAsArrayBuffer(file as Blob);
    }
  }

  async acceptUrl() {
    this.visible = false;
    if (this.crop) {
      try {
        const urlBlobResponse: Blob = await axios.get(this.imageUrl as string, {
          responseType: "blob", // This ensures the data is returned as a Blob
        });
        const fullUrl = new URL(this.imageUrl as string);
        const fileName = fullUrl.pathname.split("/").pop() as string;
        (this.$refs.photoDialog as PhotoDialog).open(
          this.imageCallback,
          this.claimType,
          this.crop,
          urlBlobResponse.data as Blob,
          fileName,
        );
      } catch (error) {
        this.$notify(
          {
            group: "alert",
            type: "danger",
            title: "Error",
            text: "There was an error retrieving that image.",
          },
          5000,
        );
      }
    } else {
      this.imageCallback(this.imageUrl);
    }
  }

  close() {
    this.visible = false;
  }
}
</script>

<style>
.dialog-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(0, 0, 0, 0.5);
  display: flex;
  justify-content: center;
  align-items: center;
  padding: 1.5rem;
}

.dialog {
  background-color: white;
  padding: 1rem;
  border-radius: 0.5rem;
  width: 100%;
  max-width: 700px;
}
</style>
