/*= require vue_common_component/commit
/*= require ./environment_actions
/*= require ./environment_external_url
/* globals Vue, timeago */

(() => {
  /**
   * Envrionment Item Component
   *
   * Used in a hierarchical structure to show folders with children
   * in a table.
   * Recursive component based on [Tree View](https://vuejs.org/examples/tree-view.html)
   *
   * See this [issue](https://gitlab.com/gitlab-org/gitlab-ce/issues/22539)
   * for more information.
   */

  window.gl = window.gl || {};
  window.gl.environmentsList = window.gl.environmentsList || {};

  gl.environmentsList.EnvironmentItem = Vue.component('environment-item', {

    components: {
      'commit-component': window.gl.CommitComponent,
      'actions-component': window.gl.environmentsList.ActionsComponent,
      'external-url-component': window.gl.environmentsList.ExternalUrlComponent,
    },

    props: ['model', 'can-create-deployment', 'can-create-deployment', 'can-read-environment'],

    data() {
      return {
        open: false,
        rowClass: {
          'children-row': this.model['vue-isChildren'],
        },
      };
    },

    computed: {

      /**
       * If an item has a `children` entry it means it is a folder.
       * Folder items have different behaviours - it is possible to toggle
       * them and show their children.
       *
       * @returns {Boolean}
       */
      isFolder() {
        return this.$options.hasKey(this.model, 'children') &&
          this.model.children.length > 0;
      },

      /**
       * If an item is inside a folder structure will return true.
       * Used for css purposes.
       *
       * @returns {Boolean|undefined}
       */
      isChildren() {
        return this.model['vue-isChildren'];
      },

      /**
       * Counts the number of environments in each folder.
       * Used to show a badge with the counter.
       *
       * @returns {Boolean}  The number of environments for the current folder
       */
      childrenCounter() {
        return this.$options.hasKey(this.model, 'children') &&
          this.model.children.length;
      },

      /**
       * Returns the value of the `last?` key sent in the API.
       * Used to know wich title to render when the environment can be re-deployed
       *
       * @returns {Boolean}
       */
      isLast() {
        return this.$options.hasKey(this.model, 'last_deployment') &&
          this.model.last_deployment['last?'];
      },

      /**
       * Verifies if `last_deployment` key exists in the current Envrionment.
       * This key is required to render most of the html - this method works has
       * an helper.
       *
       * @returns {Boolean}
       */
      hasLastDeploymentKey() {
        return this.$options.hasKey(this.model, 'last_deployment');
      },

      /**
       * Verifies is the given environment has manual actions.
       * Used to verify if we should render them or nor.
       *
       * @returns {Boolean}
       */
      hasManualActions() {
        return this.$options.hasKey(this.model, 'manual_actions') &&
          this.model.manual_actions.length;
      },

      /**
       * Returns the value of the `stoppable?` key provided in the response.
       *
       * @returns {Boolean}
       */
      isStoppable() {
        return this.model['stoppable?'];
      },

      /**
       * Verifies if the `deployable` key is present in `last_deployment` key.
       * Used to verify whether we should or not render the rollback partial.
       *
       * @returns {Boolean}
       */
      canRetry() {
        return this.hasLastDeploymentKey &&
          this.model.last_deployment &&
          this.$options.hasKey(this.model.last_deployment, 'deployable');
      },

      /**
       * Human readable date.
       *
       * @returns {String}
       */
      createdDate() {
        const timeagoInstance = new timeago();

        return timeagoInstance.format(this.model.created_at);
      },

      /**
       * Verifies if the environment has any manual actions to be rendered.
       *
       * @returns {Boolean}
       */
      hasManualActions() {
        return this.model.last_deployment &&
          this.model.last_deployment.manual_actions &&
          this.model.last_deployment.manual_actions.length > 0;
      },

      /**
       * Returns the manual actions with the name parsed.
       *
       * @returns {Array.<Object>}
       */
      manualActions() {
        return this.model.last_deployment.manual_actions.map((action) => {
          const parsedAction = {
            name: gl.text.humanize(action.name),
            play_url: action.play_url,
          };
          return parsedAction;
        });
      },

      userImageAltDescription() {
        return `${this.model.last_deployment.user.username}'s avatar'`;
      },

      /**
       * If provided, returns the commit tag.
       *
       * @returns {String|Undefined}
       */
      commitTag() {
        if (this.model.last_deployment && this.model.last_deployment.tag) {
          return this.model.last_deployment.tag;
        }
        return undefined;
      },

      /**
       * If provided, returns the commit ref.
       *
       * @returns {Object|Undefined}
       */
      commitRef() {
        if (this.model.last_deployment && this.model.last_deployment.ref) {
          return this.model.last_deployment.ref;
        }
        return undefined;
      },

      /**
       * If provided, returns the commit url.
       *
       * @returns {String|Undefined}
       */
      commitUrl() {
        if (this.model.last_deployment &&
          this.model.last_deployment.commit &&
          this.model.last_deployment.commit.commit_url) {
          return this.model.last_deployment.commit.commit_url;
        }
        return undefined;
      },

      /**
       * If provided, returns the commit short sha.
       *
       * @returns {String|Undefined}
       */
      commitShortSha() {
        if (this.model.last_deployment &&
          this.model.last_deployment.commit &&
          this.model.last_deployment.commit.short_id) {
          return this.model.last_deployment.commit.short_id;
        }
        return undefined;
      },

      /**
       * If provided, returns the commit title.
       *
       * @returns {String|Undefined}
       */
      commitTitle() {
        if (this.model.last_deployment &&
          this.model.last_deployment.commit &&
          this.model.last_deployment.commit.title) {
          return this.model.last_deployment.commit.title;
        }
        return undefined;
      },

      /**
       * If provided, returns the commit tag.
       *
       * @returns {Object|Undefined}
       */
      commitAuthor() {
        if (this.model.last_deployment &&
          this.model.last_deployment.commit &&
          this.model.last_deployment.commit.author) {
          return this.model.last_deployment.commit.author;
        }

        return undefined;
      },

      canReadEnvironmentParsed() {
        return this.$options.convertPermissionToBoolean(this.canReadEnvironment);
      },

      canCreateDeploymentParsed() {
        return this.$options.convertPermissionToBoolean(this.canCreateDeployment);
      },
    },

    /**
     * Helper to verify if key is present in an object.
     * Can be removed once we start using lodash.
     *
     * @param  {Object} obj
     * @param  {String} key
     * @returns {Boolean}
     */
    hasKey(obj, key) {
      return {}.hasOwnProperty.call(obj, key);
    },

    /**
     * Converts permission provided as strings to booleans.
     * @param  {String} string
     * @returns {Boolean}
     */
    convertPermissionToBoolean(string) {
      if (string === 'true') {
        return true;
      }

      return false;
    },

    methods: {
      /**
       * Toggles the visibility of a folders' children.
       */
      toggle() {
        if (this.isFolder) {
          this.open = !this.open;
        }
      },
    },

    template: `
      <tr>
        <td v-bind:class="rowClass">
          <a v-if="!isFolder" class="environment-name" :href="model.environment_url">
            {{model.name}}
          </a>
          <span v-else v-on:click="toggle" class="folder-name">
            <span class="folder-icon">
              <i v-show="open" class="fa fa-caret-down"></i>
              <i v-show="!open" class="fa fa-caret-right"></i>
            </span>

            {{model.name}}

            <span class="badge">
              {{childrenCounter}}
            </span>
          </span>
        </td>

        <td class="deployment-column">
          <span v-if="!isFolder && model.last_deployment && model.last_deployment.iid">
            #{{model.last_deployment.iid}}

            <span v-if="model.last_deployment.user">
              by
              <a :href="model.last_deployment.user.web_url">
                <img class="avatar has-tooltip s20"
                  :src="model.last_deployment.user.avatar_url"
                  :alt="userImageAltDescription"
                  :title="model.last_deployment.user.username" />
              </a>
            </span>
          </span>
        </td>

        <td>
          <a v-if="!isFolder && model.last_deployment && model.last_deployment.deployable"
            class="build-link"
            :href="model.last_deployment.deployable.build_url">
            {{model.last_deployment.deployable.name}} #{{model.last_deployment.deployable.id}}
          </a>
        </td>

        <td>
          <div v-if="!isFolder && model.last_deployment">
            <commit-component
              :tag="commitTag"
              :ref="commitRef"
              :commit_url="commitUrl"
              :short_sha="commitShortSha"
              :title="commitTitle"
              :author="commitAuthor">
            </commit-component>
          </div>
          <p v-if="!isFolder && !model.last_deployment" class="commit-title">
            No deployments yet
          </p>
        </td>

        <td>
          <span v-if="!isFolder && model.last_deployment" class="environment-created-date-timeago">
            {{createdDate}}
          </span>
        </td>

        <td class="hidden-xs">
          <div v-if="!isFolder">
            <div v-if="hasManualActions && canCreateDeploymentParsed">
              <actions-component :actions="manualActions"></actions-component>
            </div>
            
            <div v-if="model.external_url && canReadEnvironmentParsed">
              <external-url-component 
                :external_url="model.external_url">
              </external_url-component>
            </div>
          </div>
        </td>
      </tr>

      <tr v-if="open && isFolder"
        is="environment-item"
        v-for="model in model.children"
        :model="model">
      </tr>
    `,
  });
})();