<template>
  <div id="page_view" class="view page-view">
    <div class="view-title">
      <h1>{{ (!!title) ? title : "Untitled" }}</h1>
    </div>
    <div class="view-content">
      <div class="top">
        <div class="page-title-container">
          <input type="text" title="Page Title" placeholder="Page Title" v-model="title" />
          <dropdown class="dark" :options="otherPages" option-label="title" placeholder="(no parent)" v-model="parentPage" />
        </div>
        <div class="permalink-container">
          <span>Permalink: &nbsp;</span>
          <template v-if="!editSlug">
            <span class="clickable">
              <a :href="siteDomain + '/' + slug">{{ siteDomain }}/{{ slug }}</a>
            </span>
          </template>
          <template v-else>
            <span>{{ siteDomain }}/</span>
            <div class="slug">
              <span v-if="!editSlug">{{ slug }}</span>
              <input type="text" title="Page Slug" v-model="slug" v-if="!!editSlug" />
            </div>
          </template>
          <a @click="editSlug = !editSlug" class="icon-container"><i class="fas fa-pencil"></i></a>
        </div>
      </div>
      <div class="page-builder-container" :class="{ empty: (!components || components.length === 0) && !chooseComponent }">
        <div class="component-group" :class="(!!group.groupable) ? group.name + '-component-group groupable' : group.name + '-component-group'" v-for="group in groupedComponents" v-if="!!groupedComponents">
          <div class="row" v-for="(subset, index) in group.components">
            <div class="component-headers" :class="'group-of-' + subset.length" v-if="!!group.groupable && subset.length > 0">
              <div class="header" :class="{ closed: !!component.closed }" @click="toggleComponentClose(component, subset, group)" v-for="component in subset">
                <div class="left">
                  <div class="move-container">
                    <a class="icon-container" title="Move Up" @click.stop="moveUp(component.order-1)" v-if="component.order > 1">
                      <i class="far fa-arrow-up"></i>
                    </a>
                    <a class="icon-container" title="Move Down" @click.stop="moveDown(component.order-1)" v-if="component.order < components.length">
                      <i class="far fa-arrow-down"></i>
                    </a>
                  </div>
                  <span class="name">{{ component.name }}</span>
                </div>
                <div class="right">
                  <a class="icon-container" @click.stop="component.showActions = !component.showActions">
                    <i class="far fa-ellipsis-v fa-fw"></i>
                  </a>
                  <div class="component-actions" v-show="!!component.showActions" v-on-clickaway="() => component.showActions = false">
                    <div class="grid-container">
                      <div class="action duplicate" @click.stop="duplicate(component, component.order-1)">
                        <div class="icon-container">
                          <i class="far fa-copy"></i>
                        </div>
                        <span class="text">Duplicate</span>
                      </div>
                      <div class="action delete" @click.stop="removeComponent(component, component.order-1)">
                        <div class="icon-container">
                          <i class="fas fa-trash"></i>
                        </div>
                        <span class="text">Delete</span>
                      </div>
                      <div class="action save-to-vault" @click.stop="saveToVault(component)">
                        <div class="icon-container">
                          <i class="fas fa-save"></i>
                        </div>
                        <span class="text">Save to Vault</span>
                      </div>
                      <div class="action ungroup" @click.stop="ungroup(component.order-1)" v-if="!!component.is_grouped">
                        <div class="icon-container">
                          <i class="far fa-layer-group"></i>
                        </div>
                        <span class="text">Ungroup</span>
                      </div>
                    </div>
                  </div>
                </div>
              </div>
            </div>

            <div class="component-container" v-for="component in subset" v-if="!!components && components.length > 0">
              <div class="header" :class="{ closed: !!component.closed }" @click="toggleComponentClose(component, subset, group)" v-if="!group.groupable && index === 0 && !!component">
                <div class="left">
                  <div class="move-container">
                    <a class="icon-container" title="Move Up" @click.stop="moveUp(component.order-1)" v-if="component.order > 1">
                      <i class="far fa-arrow-up"></i>
                    </a>
                    <a class="icon-container" title="Move Down" @click.stop="moveDown(component.order-1)" v-if="component.order < components.length">
                      <i class="far fa-arrow-down"></i>
                    </a>
                  </div>
                  <span class="name">{{ component.name }}</span>
                </div>
                <div class="right">
                  <a class="icon-container" @click.stop="component.showActions = !component.showActions">
                    <i class="far fa-ellipsis-v fa-fw"></i>
                  </a>
                  <div class="component-actions" v-show="!!component.showActions" v-on-clickaway="() => component.showActions = false">
                    <div class="grid-container">
                      <div class="action duplicate" @click.stop="duplicate(component, component.order-1)">
                        <div class="icon-container">
                          <i class="far fa-copy"></i>
                        </div>
                        <span class="text">Duplicate</span>
                      </div>
                      <div class="action delete" @click.stop="removeComponent(component, component.order-1)">
                        <div class="icon-container">
                          <i class="fas fa-trash"></i>
                        </div>
                        <span class="text">Delete</span>
                      </div>
                      <div class="action save-to-vault" @click.stop="saveToVault(component)">
                        <div class="icon-container">
                          <i class="fas fa-save"></i>
                        </div>
                        <span class="text">Save to Vault</span>
                      </div>
                    </div>
                  </div>
                </div>
              </div>
              <div class="body" v-show="!component.closed" v-if="!!component">
                <div class="tabbed-content">
                  <div class="tabs">
                    <a class="tab" :class="{ active : (component.currentTab === tab) }" @click="component.currentTab = tab" v-for="tab in componentTabs">
                      {{ tab }}
                    </a>
                  </div>
                  <div class="tab-view" v-if="!!component.content">
                    <component-content :component-slug="component.slug" :properties.sync="component.content.properties" :index="component.order-1" v-show="component.currentTab === 'Content'" />
                    <component-colors :properties.sync="component.content.colors" v-show="component.currentTab === 'Colors'" />
                    <component-background :properties.sync="component.content.background" :index="component.order-1" v-show="component.currentTab === 'Background'" />
                    <component-additional-options :properties.sync="component.content.additionalOptions" :index="component.order-1" v-show="component.currentTab === 'Additional Options'" />
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>

        <div class="button-container" v-if="!!components && components.length > 0 && !chooseComponent">
          <a class="button dark-gray" @click="chooseComponent = true">Add Component</a>
        </div>

        <div class="component-picker" v-if="!!chooseComponent">
          <div class="tabs">
            <a class="tab" :class="{ active : (currentCategoryTab === category) }" @click="currentCategoryTab = category" v-for="category in categoryTabs">{{ category }}</a>
          </div>
          <div class="tab-view">
            <div class="head">
              <div class="title">
                Add a New Component
              </div>
              <a class="icon-container" @click="chooseComponent = false">
                <i class="far fa-times"></i>
              </a>
            </div>
            <component :is="currentCategoryTabComponent" :components="currentCategoryTabProperties" @select="addComponent"></component>
          </div>
        </div>

        <div class="empty-state" v-if="(!components || components.length === 0) && !chooseComponent">
          <h1>Get Started</h1>
          <span>add a component</span>
          <a class="button" @click="chooseComponent = true">Add New</a>
        </div>
      </div>
      <div class="additional-container">
        <div class="additional-input-container seo-description-container">
          <div class="label">
            SEO Description
          </div>
          <div class="input">
            <textarea v-model="seoDescription"></textarea>
          </div>
        </div>
      </div>
    </div>

    <modal
      v-if="!!activeUser && !sameUser"
      header-text="Whoops! Someone is already working on this page!"
      :body-text="lockdownMessage"
      :buttons="buttons"
      class="dark"
    />

  </div>
</template>

<script>
  import { mixin as clickaway } from 'vue-clickaway2';
  import { get, post, put } from '../helpers/api.js';

  import Modal from '../components/Modal';

  export default {
    mixins: [ clickaway ],
    data() {
      return {
        paramSlug: this.$route.params['slug'],
        id: null,
        title: null,
        parentPage: null,
        otherPages: [],
        siteDomain: document.location.origin,
        seoDescription: null,
        editSlug: false,
        chooseComponent: false,
        categoryTabs: [ "Visual", "Grouped", "Short Format", "Long Format", "Functional" ],
        componentsByCategory: null,
        currentCategoryTab: "Visual",
        components: [],
        componentTabs: [ "Content", "Colors", "Background", "Additional Options" ],
        deletedComponents: [],
        currentUser: this.$store.state.storage.whoami,
        activeUser: null,
        sameUser: false,
        buttons: [
            {
                text: "Pages",
                callback: () => {
                    this.$router.push("/pages");
                },
                classes: "gray"
            },
            {
                text: "Try Again",
                callback: () => {
                    window.location.reload(true)
                }
            }
        ]
      };
    },
    created() {
      window.addEventListener('beforeunload', this.removeActiveUser);

      this.$store.commit('concludeAddNew');
      this.initData();
    },
    beforeDestroy() {
        if (!!this.paramSlug) {
            this.removeActiveUser();
        }
    },
    computed: {
      slug: {
        get() {
          if (!!this.title) {
            return this.slugify(this.title);
          }
          else {
            return 'untitled';
          }
        },
        set(val) {
          // const regex = /^[a-z0-9]+(?:-[a-z0-9]+)*$/gi;
          // console.log(val);
          // console.log(val.replace(regex, ''));
        }
      },
      lockdownMessage: {
          get() {
              if (!!this.activeUser) {
                  return `${this.activeUser.first_name} ${this.activeUser.last_name} is
              already working on this page! Only one person can edit the page at a time.`;
              } else {
                  return `A user is
              already working on this page! Only one person can edit the page at a time.`;
              }

          },
          set() {

          }
      },
      currentCategoryTabComponent: function() {
        return 'category-' + this.slugify(this.currentCategoryTab);
      },
      currentCategoryTabProperties: function() {
        return this.componentsByCategory[this.currentCategoryTab];
      },
      statusMask: function() {
        return this.$store.state.variables.statusMask;
      },
      pagePassword: function() {
        return this.$store.state.variables.pagePassword;
      },
      groupedComponents: function() {
        let groupedObject = null;

        if (!!this.components && !!this.components.length) {
          const self = this;
          groupedObject = {};
          let index = 1;
          let currentKeyName = index + "-" + this.components[0].name;
          this.components.forEach( function(component, i) {
            component.order = i+1;

            if (i !== 0 && (index + "-" + component.name) === currentKeyName && !!component.is_grouped) {
              groupedObject[currentKeyName].groupable = true;
              groupedObject[currentKeyName].components.push(component);
            }
            else if (i === 0 || (i !== 0 && (index + "-" + component.name) !== currentKeyName) || !component.is_grouped) {
              if (i !== 0) {
                index++;
                currentKeyName = index + "-" + component.name;
              }
              groupedObject[currentKeyName] = {};
              groupedObject[currentKeyName].name = self.slugify(component.name);
              groupedObject[currentKeyName].groupable = component.is_grouped;
              groupedObject[currentKeyName].components = [];
              groupedObject[currentKeyName].components.push(component);
            }
          });

          for (let group in groupedObject) {
            if (groupedObject.hasOwnProperty(group)) {
              let name = groupedObject[group].name;
              let numberOnRow = 4;
              if (name === "card") {
                numberOnRow = 3;
              }
              else if (name === "complex-button" || name === "text" || name === "side-by-side") {
                numberOnRow = 2;
                if (name === "side-by-side" && groupedObject[group].components.length === 2) {
                  numberOnRow = 1;
                }
              }

              let newArray = [];

              if ((name === "text" || name === "side-by-side") && groupedObject[group].components.length % 2 !== 0) {
                  newArray.push([]);
                  newArray[0].push(groupedObject[group].components.shift());
              }

              while (groupedObject[group].components.length) {
                newArray.push(groupedObject[group].components.splice(0, numberOnRow))
              }

              groupedObject[group].components = newArray;
            }
          }
        }

        return groupedObject;
      },
      isSaving: function() {
        return this.$store.state.actions.saving;
      },
      isAddingNew: function() {
        return this.$store.state.actions.addingNew;
      },
      isDeleting: function() {
        return this.$store.state.actions.deleting;
      }
    },
    watch: {
      isSaving: function (isSaving) {
        if (!!isSaving) {
          this.submit();
        }
      },
      isAddingNew: function(isAddingNew) {
        if (!!isAddingNew) {
          console.log("Adding new......");
          this.$router.push("/pages/new");
          this.resetData();
          this.$store.commit('concludeAddNew');
        }
      },
      isDeleting: function(isDeleting) {
        if (!!isDeleting) {
          this.delete();
        }
      }
    },
    methods: {
      slugify(text) {
        if (!!text) {
          return text.trim()
            .toLowerCase()
            .replace(/[^a-z0-9-]/gi, '-')
            .replace(/_+/g, '-')
            .replace(/^-|-$/g, '');
        }
      },
      doUsersMatch() {
          if (!!this.currentUser || !!this.activeUser) {
              return true;
          }

          return this.activeUser.id === this.currentUser.id;
      },
      initData() {
        const self = this;
        if (!!this.paramSlug) {
          get('buildable_pages/' + this.paramSlug, window.jwtToken)
            .then( (res) => {
              if (!!res && !!res.data && !!res.data.page && !!res.data.other_pages) {
                this.activeUser = res.data.page.active_user;

                if (!!this.activeUser) {
                    this.sameUser = this.activeUser.id === this.currentUser.id;
                } else {
                    this.sameUser = false;
                }

                this.id = res.data.page.id;
                this.title = res.data.page.title;
                this.slug = res.data.page.slug;
                this.parentPage = this.otherPages.find( function(page) {
                  return page.id = res.data.page.parent_id;
                });
                this.$store.commit('setStatus', res.data.page.status_mask);
                this.otherPages = res.data.other_pages;
                res.data.page.metas.forEach( function(meta) {
                  if (meta.key === "Password") {
                    self.$store.commit("setPagePassword", meta.value);
                  }
                  else if (meta.key === "SEO Description") {
                    self.seoDescription = meta.value;
                  }
                });
                this.components = res.data.page.components.map( function(component) {
                  component.content = JSON.parse(component.content);
                  component.closed = true;
                  component.showActions = false;
                  component.currentTab = "Content";
                  return component;
                });

                this.components.sort( function(a, b) {
                  return a.order - b.order;
                });
              }
            })
            .catch( (err) => {
              console.log(err);
            });
        }
        else {
          get('buildable_pages', window.jwtToken)
            .then( (res) => {
              if (!!res && !!res.data && !!res.data.pages) {
                this.otherPages = res.data.pages;
              }
            })
            .catch( (err) => {
              console.log(err);
            });
        }

        get('buildable_json_by_category', window.jwtToken)
          .then( (res) => {
            if (!!res && !!res.data && !!res.data.buildable_json_by_category) {
              this.componentsByCategory = res.data.buildable_json_by_category;
            }
          })
          .catch( (err) => {
            console.log(err);
          });

        this.$store.commit('getFiles');
      },
      resetData() {
        this.paramSlug = undefined;
        this.title = this.parentPage = null;
        this.otherPages = this.components = [];
        this.editSlug = this.chooseComponent = false;
        this.currentCategoryTab = "Visual";

        this.initData();
      },
      removeActiveUser() {

          if (this.currentUser == null) {
              return
          }

          if (!!this.activeUser && this.activeUser.id !== this.currentUser.id) {
              return;
          }

          if (!!this.paramSlug) {
            put(`buildable_pages/unset_active_user/${this.paramSlug}`, null, window.jwtToken)
              .then( (res) => {
                // Do something with the returned BuildablePage Model (fresh)
              })
              .catch( (err) => {
                if (err.response.status != 403) {
                  alert("Page's active user could not be removed.");
                }
                console.error(err);
              });
          }


      },
      addComponent(component) {
        const componentClone = _.cloneDeep(component);

        const properties = componentClone.properties;
        componentClone.content = {
          properties: properties,
          colors: {
            backgroundColor: "light",
            accentColor: "primary-color"
          },
          background: {
            size: "fit",
            image: null,
            fixed: false,
            angledTop: false,
            angledBottom: false
          },
          additionalOptions: {
            anchor: null,
            classes: null,
            removeTopPadding: false,
            removeBottomPadding: false,
            negativeTopMargin: false,
            negativeBottomMargin: false,
            hideOnMobile: false,
            hideOnDesktop: false
          }
        };
        delete componentClone.properties;

        componentClone.closed = false;
        componentClone.showActions = false;
        componentClone.currentTab = "Content";

        if (!!this.groupedComponents) {
          const lastKey = Object.keys(this.groupedComponents)[Object.keys(this.groupedComponents).length - 1];
          const lastComponentName = lastKey.substring(lastKey.indexOf('-') + 1);

          if (componentClone.name === lastComponentName && !!this.groupedComponents[lastKey].groupable) {
            this.groupedComponents[lastKey].components.forEach( function(subset) {
              subset.forEach( function(component) {
                component.closed = true;
              });
            });
          }
        }

        this.components.push(componentClone);
        this.chooseComponent = false;
      },
      toggleComponentClose(component, subset, group) {
        if (!!component.closed && !!group.groupable && subset.length > 1) {
          subset.forEach( function(component) {
            component.closed = true;
          });
        }
        component.closed = !component.closed;
      },
      removeComponent(component, index) {
        this.components.splice(index, 1);
        this.deletedComponents.push(component.id);
      },
      moveUp(index) {
        this.components.splice(index-1, 2, this.components[index], this.components[index-1])
      },
      moveDown(index) {
        this.components.splice(index, 2, this.components[index+1], this.components[index])
      },
      duplicate(component, index) {
        const componentClone = _.cloneDeep(component);
        delete componentClone.id;
        componentClone.showActions = false;
        this.components.splice(index+1, 0, componentClone);
      },
      saveToVault(component) {
        console.log("Saving to Vault......");
      },
      delete() {
        if (!!this.paramSlug) {
          const form_params = {
            slug: this.slug,
            parent_id: (!!this.parentPage) ? this.parentPage.id : undefined,
            title: this.title,
            status_mask: 128,
            metas: {},
            components: this.components,
            deleted_components: this.deletedComponents
          };

          put('buildable_pages/' + this.paramSlug, form_params, window.jwtToken)
            .then( (res) => {
              if (!!res && !!res.data && !!res.data.updated_page) {
                this.$router.push("/pages");
              }
            })
            .catch( (err) => {
              console.log(err);
            });
        }
      },
      ungroup(index) {
        this.components[index].is_grouped = false;
      },
      submit() {
        const form_params = {
          slug: this.slug,
          parent_id: (!!this.parentPage) ? this.parentPage.id : undefined,
          title: this.title,
          status_mask: this.statusMask,
          metas: {},
          components: this.components
        };

        if (this.statusMask === 4 && !!this.pagePassword) {
          form_params.metas.password = { key: "Password", value: this.pagePassword };
        }
        
        if (!!this.seoDescription) {
          form_params.metas.seoDescription = { key: "SEO Description", value: this.seoDescription };
        }

        if (!this.paramSlug) {
          console.log("Saving a new page......");

          post('buildable_pages', form_params, window.jwtToken)
            .then( (res) => {
              if (!!res && !!res.data && !!res.data.new_page) {
                this.$router.push("/pages/" + res.data.new_page.slug);
                this.paramSlug = res.data.new_page.slug;

                res.data.new_page.components.sort( function(a, b) {
                  return a.order - b.order;
                });

                this.components = res.data.new_page.components.map( function(component, i) {
                  component.content = JSON.parse(component.content);
                  component.closed = form_params.components[i].closed;
                  component.showActions = false;
                  component.currentTab = "Content";
                  return component;
                });
              }
            })
            .catch( (err) => {
              console.log(err);
            });
        }
        else {
          console.log("Saving an existing page......");
          form_params.id = this.id;
          form_params.deleted_components = this.deletedComponents;

          put('buildable_pages/' + this.paramSlug, form_params, window.jwtToken)
            .then( (res) => {
              if (!!res && !!res.data && !!res.data.updated_page) {
                if (res.data.updated_page.status_mask === 128) {
                  this.$router.push("/pages");
                }

                res.data.updated_page.components.sort( function(a, b) {
                  return a.order - b.order;
                });

                this.components = res.data.updated_page.components.map( function(component, i) {
                  component.content = JSON.parse(component.content);
                  component.closed = form_params.components[i].closed;
                  component.showActions = false;
                  component.currentTab = form_params.components[i].currentTab;
                  return component;
                });

                this.deletedComponents = [];
              }
            })
            .catch( (err) => {
              console.log(err);
            });
        }
        this.$store.commit('concludeSave');
      }
    }
  }
</script>
