<template>
  <div class="flex">
    <div
      class="lg:mr-4 tools"
      ref="tools"
    >
      <div class="mb-2 flex flex-row">
        <button
          v-for="(name, value) in tools"
          class="p-3 mr-2 rounded"
          :class="{'bg-slate-300': this.tool == value}"
          @click="this.tool = value"
          v-text="name"
        ></button>
      </div>

      <div
        :class="{hidden: this.tool !== 'heading'}"
        class="drop-shadow-md rounded-md md:border border-zinc-300 tool"
      >
        <div class="p-5">
          <div>
            <TextareaForm
              id="heading"
              v-model="heading"
              label="Heading"
            />
            <RangeForm
              id="heading-size"
              v-model="headingSize"
              min="1"
              max="20"
              step="0.1"
            />
          </div>

          <div class="py-6">
            <TextareaForm
              id="subheading"
              v-model="subheading"
              label="Subheading"
            />
            <RangeForm
              id="subheading-size"
              v-model="subheadingSize"
              min="1"
              max="20"
              step="0.1"
            />
          </div>

          <div class="pb-6">
            <CheckboxForm
              id="allow-html"
              v-model="allowHtml"
              label="Allow HTML"
            />
          </div>

          <div class="pb-6">
            <RangeForm
              id="heading-spacing"
              v-model="headingSpacing"
              min="0"
              max="300"
              step="0.05"
              label="Spacing"
            />
          </div>

          <div class="pb-6">
            <RangeForm
              id="content-padding"
              v-model="contentPadding"
              min="0"
              max="300"
              step="0.05"
              label="Padding"
            />
          </div>

          <div class="pb-3">
            <InputForm
              id="text-color"
              v-model="textColor"
              label="Text color"
              type="color"
            />
          </div>

          <div>
            <div class="text-center stroke-gray-400">
              <AlignForm v-model="headingAlign" />
            </div>
          </div>
        </div>
      </div>

      <div
        :class="{hidden: this.tool !== 'author'}"
        class="drop-shadow-md rounded-md md:border border-zinc-300 tool"
      >
        <div class="p-5">
          <div>
            <InputForm
              id="author"
              v-model="author"
              label="Author"
            />
          </div>
          <div class="py-6">
            <FileForm
              id="avatar"
              v-model="avatar"
              label="Avatar"
            />
          </div>

          <div>
            <FileForm
              id="logo"
              v-model="logo"
              label="Logo"
            />
          </div>

          <div class="stroke-gray-400 py-6">
            <RangeForm
              id="author-margin-bottom"
              v-model="authorMarginBottom"
              min="0"
              max="500"
              step="0.1"
              label="Position"
            />
            <RangeForm
              id="author-padding"
              v-model="authorPadding"
              min="0"
              max="50"
              step="0.05"
              label="Padding"
            />
          </div>

          <div class="pb-3">
            <InputForm
              id="author-text-color"
              v-model="authorTextColor"
              label="Text color"
              type="color"
            />
          </div>

          <div>
            <InputForm
              id="background-color"
              v-model="authorBackgroundColor"
              label="Background color"
              type="color"
            />
            <RangeForm
              id="author-background-opacity"
              v-model="authorBackgroundOpacity"
              min="0"
              max="1"
              step="0.05"
            />
          </div>

          <div>
            <div class="text-center stroke-gray-400 pt-5">
              <AlignForm v-model="authorAlign" />
            </div>
          </div>
        </div>
      </div>

      <div
        :class="{hidden: this.tool !== 'font'}"
        class="drop-shadow-md rounded-md md:border border-zinc-300 tool"
      >
        <div class="p-5">
          <SelectForm
            id="font"
            v-model="font"
            :items="fonts"
            label="Font"
          />
        </div>
      </div>

      <div
        :class="{hidden: this.tool !== 'background'}"
        class="drop-shadow-md rounded-md md:border border-zinc-300 tool"
      >
        <div class="p-5">
          <div class="pb-6">
            <FileForm
              id="background"
              v-model="background"
              label="Background"
            />
          </div>

          <div>
            <InputForm
              id="background-hover"
              v-model="backgroundHover"
              label="Background hover"
              type="color"
            />
            <RangeForm
              id="background-hover-opacity"
              v-model="backgroundHoverOpacity"
              min="0"
              max="1"
              step="0.05"
            />
          </div>
        </div>
      </div>
      <div
        :class="{hidden: this.tool !== 'sizes'}"
        class="drop-shadow-md rounded-md md:border border-zinc-300 tool"
      >
        <div class="p-5">
          <div>
            <label
              class="block text-sm font-medium text-gray-700"
              for="width"
            >Sizes</label>

            <div class="grid grid-cols-2 gap-x-4">
              <InputForm
                id="width"
                v-model="width"
                type="number"
              />
              <InputForm
                id="height"
                v-model="height"
                type="number"
              />
            </div>

            <h3 class="mt-4 block text-sm font-medium text-gray-700">Recommendations</h3>

            <button
              v-for="(sizes, name) in sizesRecommendations"
              class="bg-lime-300 rounded px-3 py-2 mt-1 mr-1"
              @click="this.setSizes(sizes[0], sizes[1])"
              v-text="name"
            ></button>
          </div>
        </div>
      </div>
    </div>
    <div
      ref="ogwrapper"
      class="og-wrapper lg:pl-10"
    >
      <svg data-marpit-svg :viewBox="[0, 0, width, height].join(' ')">
        <foreignObject
          :width="width"
          :height="height"
          :style="ogSvgStyle()"
        >
          <div class="og-wrapper-content">
            <div
              ref="og"
              class="og"
              :style="ogStyle()"
            >
              <div
                class="og-image"
                ref="ogimage"
                :style="ogImageStyle()"
              >
                <div
                  class="og-image-hover"
                  :style="ogImageHoverStyle()"
                >
                  <div
                    class="h-full flex flex-col justify-between"
                    :style="ogContentStyle()"
                  >
                    <div v-if="allowHtml">
                      <h1
                        class="leading-none"
                        :style="ogHeadingStyle()"
                        v-html="heading"
                      />
                      <p
                        class="leading-tight"
                        :style="ogSubheadingStyle()"
                        v-html="subheading"
                      />
                    </div>
                    <div v-else>
                      <h1
                        class="leading-none"
                        :style="ogHeadingStyle()"
                        v-text="heading"
                      />
                      <p
                        class="leading-tight"
                        :style="ogSubheadingStyle()"
                        v-text="subheading"
                      />
                    </div>


                    <div
                      class="w-full flex flex-row items-center og-image--footer"
                      :style="ogAuthorStyle()"
                    >
                      <img
                        v-if="avatar"
                        class="h-10 w-10 rounded-full"
                        :src="avatar"
                      >

                      <span
                        class="mx-4"
                        :style="ogAuthorTextStyle()"
                        v-text="author"
                      />

                      <img
                        v-if="logo"
                        class="h-10 w-10 rounded-full"
                        :src="logo"
                      >
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </foreignObject>
      </svg>
      <div class="text-center mt-3">
        <DownloadButton
          class="rounded-l-md"
          label="PNG"
          @click="downloadAsPng"
        />
        <DownloadButton
          class="rounded-r-md"
          label="JPEG"
          @click="downloadAsJpeg"
        />
      </div>
    </div>
  </div>
</template>

<script>
import { hexToRgb } from '../util/color'
import { toPng, toJpeg } from 'html-to-image'
import InputForm from '../ui/InputForm'
import RangeForm from '../ui/RangeForm'
import TextareaForm from '../ui/TextareaForm'
import FileForm from '../ui/FileForm'
import SelectForm from '../ui/SelectForm'
import CheckboxForm from '../ui/CheckboxForm'
import AlignForm from '../ui/AlignForm'
import DownloadButton from '../ui/DownloadButton'

export default {
  components: {
    InputForm,
    RangeForm,
    TextareaForm,
    FileForm,
    SelectForm,
    CheckboxForm,
    AlignForm,
    DownloadButton,
  },
  data() {
    return {
      tool: localStorage.getItem('tool') ?? 'heading',
      author: localStorage.getItem('author') ?? 'Author name',
      authorPadding: localStorage.getItem('authorPadding') ?? 10,
      authorAlign: localStorage.getItem('authorAlign') ?? 'left',
      authorTextColor: localStorage.getItem('authorTextColor') ?? '#fff9e6',
      authorMarginBottom: localStorage.getItem('authorMarginBottom') ?? 200,
      authorBackgroundColor: localStorage.getItem('authorBackgroundColor') ?? '#fc5705',
      authorBackgroundOpacity: localStorage.getItem('authorBackgroundOpacity') ?? 1,
      heading: localStorage.getItem('heading') ?? 'Heading',
      subheading: localStorage.getItem('subheading') ?? 'Subheading',
      headingSpacing: localStorage.getItem('headingSpacing') ?? 10,
      headingAlign: localStorage.getItem('headingAlign') ?? 'left',
      font: localStorage.getItem('font') ?? 'Trebuchet MS',
      avatar: localStorage.getItem('avatar'),
      logo: localStorage.getItem('logo'),
      textColor: localStorage.getItem('textColor') ?? '#fc5705',
      background: localStorage.getItem('background'),
      backgroundHover: localStorage.getItem('backgroundHover') ?? '#fff9e6',
      backgroundHoverOpacity: localStorage.getItem('backgroundHoverOpacity') ?? 1,
      headingSize: localStorage.getItem('headingSize') ?? 4,
      subheadingSize: localStorage.getItem('subheadingSize') ?? 2,
      width: localStorage.getItem('width') ?? 1200,
      height: localStorage.getItem('height') ?? 600,
      contentPadding: localStorage.getItem('contentPadding') ?? 20,
      allowHtml: localStorage.getItem('allowHtml'),
      ogMaxWidth: 100,
      tools: {
        heading: 'Heading',
        author: 'Author',
        font: 'Font',
        background: 'Background',
        sizes: 'Sizes',
      },
      sizesRecommendations: {
        Mastodon: [1200, 600],
        LinkedIn: [1200, 627],
        Instagram: [1200, 630],
        X: [1200, 675],
      },
      fonts: [
        {label: 'Arial (sans-serif)', value : 'Arial'},
        {label: 'Brush Script MT (cursive)', value : 'Brush Script MT'},
        {label: 'Calibri (sans-serif)', value : 'Calibri'},
        {label: 'Courier New (monospace)', value : 'Courier New'},
        {label: 'Garamond (serif)', value : 'Garamond'},
        {label: 'Georgia (serif)', value : 'Georgia'},
        {label: 'Tahoma (sans-serif)', value : 'Tahoma'},
        {label: 'Times New Roman (serif)', value : 'Times New Roman'},
        {label: 'Trebuchet MS (sans-serif)', value : 'Trebuchet MS'},
        {label: 'Verdana (sans-serif)', value : 'Verdana'},
      ],
    }
  },
  watch: {
    tool(value) {
      localStorage.setItem('tool', value)
    },
    author(value) {
      localStorage.setItem('author', value)
    },
    authorAlign(value) {
      localStorage.setItem('authorAlign', value)
    },
    authorPadding(value) {
      localStorage.setItem('authorPadding', value)
    },
    authorBackgroundColor(value) {
      localStorage.setItem('authorBackgroundColor', value)
    },
    authorBackgroundOpacity(value) {
      localStorage.setItem('authorBackgroundOpacity', value)
    },
    authorTextColor(value) {
      localStorage.setItem('authorTextColor', value)
    },
    authorMarginBottom(value) {
      localStorage.setItem('authorMarginBottom', value)
    },
    heading(value) {
      localStorage.setItem('heading', value)
    },
    subheading(value) {
      localStorage.setItem('subheading', value)
    },
    headingSpacing(value) {
      localStorage.setItem('headingSpacing', value)
    },
    avatar(value) {
      localStorage.setItem('avatar', value)
    },
    logo(value) {
      localStorage.setItem('logo', value)
    },
    textColor(value) {
      localStorage.setItem('textColor', value)
    },
    background(value) {
      localStorage.setItem('background', value)
    },
    backgroundHover(value) {
      localStorage.setItem('backgroundHover', value)
    },
    backgroundHoverOpacity(value) {
      localStorage.setItem('backgroundHoverOpacity', value)
    },
    headingSize(value) {
      localStorage.setItem('headingSize', value)
    },
    subheadingSize(value) {
      localStorage.setItem('subheadingSize', value)
    },
    headingAlign(value) {
      localStorage.setItem('headingAlign', value)
    },
    width(value) {
      localStorage.setItem('width', value)
    },
    height(value) {
      localStorage.setItem('height', value)
    },
    contentPadding(value) {
      localStorage.setItem('contentPadding', value)
    },
    font(value) {
      localStorage.setItem('font', value)
    },
    allowHtml(value) {
      localStorage.setItem('allowHtml', value)
    },
  },
  mounted() {
    this.updateOgMaxWidth()
    window.addEventListener('resize', this.updateOgMaxWidth, false)
  },
  methods: {
    ogSvgStyle() {
      return {
        maxHeight: `${this.ogMaxHeight}px`,
        maxWidth: `${this.ogMaxWidth}px !important`,
        aspectRatio: `${this.width}/${this.height}`,
      }
    },
    ogStyle() {
      return {
        color: this.textColor,
        fontFamily: this.font,
        maxHeight: `${this.ogMaxHeight}px`,
        maxWidth: `${this.ogMaxWidth}px !important`,
        aspectRatio: `${this.width}/${this.height}`,
      }
    },
    ogImageStyle() {
      let value = {
        aspectRatio: `${this.width}/${this.height}`,
      }

      if (this.background) {
        value.background = `url(${this.background}) center`
        value.backgroundSize = 'cover'
      }

      return value
    },
    ogHeadingStyle() {
      return {
        fontSize: `${this.headingSize}em`,
        textAlign: this.headingAlign,
      }
    },
    ogSubheadingStyle() {
      return {
        fontSize: `${this.subheadingSize}em`,
        textAlign: this.headingAlign,
        marginTop: `${this.headingSpacing}px`,
      }
    },
    ogAuthorStyle() {
      let background = 'none'

      if (this.backgroundHover) {
        const colors = hexToRgb(this.authorBackgroundColor)
        background = `rgba(${colors.red}, ${colors.green}, ${colors.blue}, ${this.authorBackgroundOpacity})`
      }

      return {
        textAlign: this.authorAlign,
        color: this.authorTextColor,
        marginBottom: `${this.authorMarginBottom}px`,
        padding: `${this.authorPadding}px`,
        marginLeft: `-${this.contentPadding}px`,
        width: `calc(${this.contentPadding * 2}px + 100%)`,
        background,
      }
    },
    ogAuthorTextStyle() {
      let value = {}

      if (this.authorAlign === 'left') {
        value.marginRight = 'auto !important'
      } else if (this.authorAlign === 'center') {
        value.marginLeft = 'auto !important'
        value.marginRight = 'auto !important'
      } else if (this.authorAlign === 'right') {
        value.marginLeft = 'auto !important'
      }

      return value
    },
    ogImageHoverStyle() {
      let background = 'none'

      if (this.backgroundHover) {
        const colors = hexToRgb(this.backgroundHover)
        background = `rgba(${colors.red}, ${colors.green}, ${colors.blue}, ${this.backgroundHoverOpacity})`
      }

      return {
        background,
        aspectRatio: `${this.width}/${this.height}`,
        maxHeight: `${this.ogMaxHeight}px`,
        maxWidth: `${this.ogMaxWidth}px`,
      }
    },
    ogContentStyle() {
      return {
        paddingTop: `${this.contentPadding}px`,
        paddingRight: `${this.contentPadding}px`,
        paddingLeft: `${this.contentPadding}px`,
      }
    },
    setSizes(width, height) {
      this.width = width
      this.height = height
    },
    downloadAsPng() {
      return this.download(toPng, 'image.png')
    },
    downloadAsJpeg() {
      return this.download(toJpeg, 'image.jpg')
    },
    download(callback, filename) {
      const element = this.$refs.ogimage

      callback(element, {
        canvasWidth: this.width,
        canvasHeight: this.height,
        quality: 1,
      })
        .then((dataUrl) => {
          const link = document.createElement('a')

          link.setAttribute('href', dataUrl)
          link.setAttribute('download', filename)
          link.click()
        })
        .catch((error) => {
          element.classList.toggle('og--scale', false)

          console.error('oops, something went wrong!', error);
        })
    },
    updateOgMaxWidth() {
      this.$refs.og.style.display = 'none'
      this.ogMaxWidth = this.$refs.ogwrapper.offsetWidth - 30
      this.ogMaxHeight = this.$refs.tools.offsetHeight - 50
      this.$refs.og.style.display = 'block'
    },
  }
}
</script>

<style>
.tool {
  max-height: calc(100vh - 250px);
  overflow: auto;
}

.tools {
  height: calc(100vh - 250px);
  width: 443px;
}

.og {
  margin: auto;
}

.og-wrapper {
  width: calc(100vw - 540px);
}

.og-wrapper-content {
  background-color: #c1c1c1;
  background-image: linear-gradient(45deg, #646464 25%, transparent 25%, transparent 75%, #646464 75%), linear-gradient(45deg, #646464 25%, transparent 25%, transparent 75%, #646464 75%);
  background-size: 20px 20px;
  background-position: 0 0, 10px 10px;
}

.og-heading {
  font-size: 5em;
}

.og-subheading {
  font-size: 3em;
}

.og-image--footer {
  font-size: 1.3em;
}

.og-image-hover {
  overflow: hidden;
}
</style>
