<template>
  <h2 class="tool-title">YAML formatter</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:keyup="result"></textarea>
  </div>

  <div class="input-group">
    <label>Sort</label>

    <div>
      <input
        id="sort_alphabetically"
        value="alphabetically"
        name="sort"
        v-model="toolData.sort"
        v-on:change="result"
        type="radio"
      />
      <label for="sort_alphabetically"> alphabetically</label><br />
      <input
        id="sort_docker_compose"
        value="docker_compose"
        name="sort"
        v-model="toolData.sort"
        v-on:change="result"
        type="radio"
      />
      <label for="sort_docker_compose"> docker-compose</label><br />
      <input
        id="sort_no"
        value="no"
        name="no"
        v-model="toolData.sort"
        v-on:change="result"
        type="radio"
      />
      <label for="sort_no"> no</label><br />
    </div>
  </div>

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

  <div class="input-group">
    <label for="result">Result</label>
    <MonacoEditor
      name="result"
      language="json"
      :value="toolResult"
    ></MonacoEditor>
  </div>
</template>

<script>
import MonacoEditor from "@/components/MonacoEditor.vue";
import { parse, stringify } from "yaml";

const orderFirst = [
  // root
  "version",
  "services",

  // other
  "labels",
  "restart",
  "environment",
  "ports",
  "volumes"
  // ... other keys to appear first
];

const orderLast = [
  "image",
  "container_name",
  "command"
  // ... other keys to appear last
];

function sortMapEntriesForDockerCompose(a, b) {
  const aFirst = orderFirst.includes(a.key.value);
  const bFirst = orderFirst.includes(b.key.value);
  const aLast = orderLast.includes(a.key.value);
  const bLast = orderLast.includes(b.key.value);

  if (aFirst && !bFirst) {
    return -1; // a comes first
  } else if (!aFirst && bFirst) {
    return 1; // b comes first
  } else if (aLast && !bLast) {
    return 1; // b comes first
  } else if (!aLast && bLast) {
    return -1; // a comes first
  } else if (aFirst && bFirst) {
    // Both in orderFirst, maintain order
    return orderFirst.indexOf(a.key.value) - orderFirst.indexOf(b.key.value);
  } else if (aLast && bLast) {
    // Both in orderLast, maintain order
    return orderLast.indexOf(a.key.value) - orderLast.indexOf(b.key.value);
  } else {
    // Neither in orderFirst nor orderLast, sort alphabetically
    return a.key.value.localeCompare(b.key.value);
  }
}

export default {
  components: {
    MonacoEditor,
  },
  data() {
    return {
      toolData: {
        data: "",
        sort: "no",
      },
      toolResult: "",
    };
  },
  methods: {
    result() {
      if (!this.toolData.data.length) {
        this.toolResult = "";
      } else {
        try {
          const yaml = parse(this.toolData.data, {
            sortMapEntries: true,
          });

          let sorter = false;
          switch (this.toolData.sort) {
            case "alphabetically":
              sorter = true;
              break;
            case "docker_compose":
              sorter = sortMapEntriesForDockerCompose;
              break;
          }

          this.toolResult = stringify(yaml, {
            singleQuote: false,
            lineWidth: 0,
            indent: 2,
            indentSeq: true,
            sortMapEntries: sorter,
          });
        } catch (e) {
          console.log(e)
          this.toolResult = "invalid syntax";
        }
      }
    },
  },
};
</script>

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