'use strict';

var projectsServiceClass = Class.extend({
  MODULE_URL: MP_SITE_URL + '/build_app/projects',
  CMDB_UPDATE_POLICY: {
    type: 'class',
    name: 'default:cfengine_internal_masterfiles_update',
    description: 'Update default policy distribution point from upstream repository. Created by Build application.'
  },

  create: function (project) {
    return this.$http.post(this.MODULE_URL + '/project', project, { cache: false });
  },

  update: function (id, project) {
    return this.$http.put(`${this.MODULE_URL}/project/${id}`, project, { cache: false });
  },

  delete: function (id) {
    return this.$http.delete(`${this.MODULE_URL}/project/${id}`, { cache: false });
  },

  push: function (id, project) {
    return this.$http.post(`${this.MODULE_URL}/push/${id}`, project, { cache: false });
  },

  localDeploy: async function (id, project) {
    return this.$http.post(`${this.MODULE_URL}/localDeploy/${id}`, project, { cache: false });
  },

  synchronizeVcsWithProject: function (id, localDeploy) {
    return this.$http.post(`${this.MODULE_URL}/synchronize/${id}?localDeploy=${localDeploy ? 'true' : 'false'}`, { cache: false });
  },

  isProjectSynchronizedWithVcs: async function (id) {
    let response = await this.$http.get(`${this.MODULE_URL}/vcsSynchronized/${id}`, { cache: false });
    return response.data;
  },

  anyProjectDeployed: function () {
    return this.$http.get(`${this.MODULE_URL}/anyProjectDeployed`, { cache: false });
  },

  get: function (id) {
    return this.$http.get(`${this.MODULE_URL}/project/${id}`, { cache: false });
  },

  list: function (limit = 10) {
    return this.$http.get(`${this.MODULE_URL}/list?limit=${limit}`, { cache: false });
  },

  createLocal: function (data) {
    return this.$http.post(this.MODULE_URL + '/local_project', data);
  },

  getModules: function (id) {
    return this.$http.get(`${this.MODULE_URL}/modules/${id}`, { cache: false });
  },

  addModule: function (projectId, name, version) {
    return this.$http.post(`${this.MODULE_URL}/module/${projectId}/${name}/${version}`, { cache: false });
  },

  addModuleByUrl: function (projectId, url) {
    return this.$http.post(`${this.MODULE_URL}/module_by_url/${projectId}`, { url }, { cache: false });
  },

  updateModule: function (projectId, name, version) {
    return this.$http.put(`${this.MODULE_URL}/module/${projectId}/${name}/${version}`, { cache: false });
  },

  removeModule: function (projectId, name, encodedName = false) {
    return this.$http.delete(`${this.MODULE_URL}/module/${projectId}/${name}/?encodedName=${encodedName ? 'true' : 'false'}`, { cache: false });
  },

  getModuleInput: function (projectId, name, encodedName = false) {
    return this.$http.get(`${this.MODULE_URL}/module_input/${projectId}/${name}/?encodedName=${encodedName ? 'true' : 'false'}`, { cache: false });
  },

  setModuleInput: function (projectId, name, data, encodedName = false) {
    return this.$http.post(`${this.MODULE_URL}/module_input/${projectId}/${name}/?encodedName=${encodedName ? 'true' : 'false'}`, data, { cache: false });
  },

  refresh: function (id) {
    return this.$http.post(`${this.MODULE_URL}/refresh/${id}`, { cache: false });
  },

  forcePull: function (id) {
    return this.$http.post(`${this.MODULE_URL}/forcePull/${id}`, { cache: false });
  },

  rebase: function (id) {
    return this.$http.post(`${this.MODULE_URL}/rebase/${id}`, { cache: false });
  },

  forceRebase: function (id) {
    return this.$http.post(`${this.MODULE_URL}/forceRebase/${id}`, { cache: false });
  },

  _getProjectsAhead: function () {
    let projects = window.localStorage.getItem('projects_ahead');
    return projects ? projects.split(',') : [];
  },
  setAhead: function (id) {
    let projects = this._getProjectsAhead();
    if (!projects.includes(id)) {
      projects.push(id);
    }
    window.localStorage.setItem('projects_ahead', projects.join(','));
    document.dispatchEvent(new Event('project_ahead_changed'));
  },

  removeAhead: function (id) {
    let projects = this._getProjectsAhead();
    if (projects.includes(id)) {
      projects.splice(projects.indexOf(id), 1);
    }
    window.localStorage.setItem('projects_ahead', projects.join(','));
    document.dispatchEvent(new Event('project_ahead_changed'));
  },

  isProjectAhead: function (id) {
    return this._getProjectsAhead().includes(id);
  },

  getCmdbItem: async function(hubKey) {
    let cmdbItem;
    try {
      cmdbItem = await this.cmdbService.getItem(hubKey, this.CMDB_UPDATE_POLICY.type, this.CMDB_UPDATE_POLICY.name);
    } catch (e) {

    }
    return cmdbItem;
  },
  deploy: async function (id, localDeploy = false) {
    await this.synchronizeVcsWithProject(id, localDeploy);

    const hubKey = await this.getHubKey();
    const cmdbItem = await this.getCmdbItem(hubKey);

    if (!cmdbItem) {
      const entry = this.cmdbService.buildEntry({
        type: this.CMDB_UPDATE_POLICY.type,
        name: this.CMDB_UPDATE_POLICY.name,
        description: this.CMDB_UPDATE_POLICY.description
      });
      await this.cmdbService.createItem(hubKey, entry);
      // agent run to set host specific data
      await this.actionService.agentRun(hubKey);
    }

    // agent run to run masterfiles-stage.sh ( bundle cfe_internal_update_from_repository )
    await this.actionService.agentRun(hubKey);
  },

  stopDeploying: async function () {
    const { data : cmdbItem } = await this.getCmdbItem(await this.getHubKey());
    if (cmdbItem) {
      await this.cmdbService.deleteItem(cmdbItem.entry_id);
    }

    await this.clearVCS();
  },

  getHubKey: async function () {
    const hubInfo = await this.hubManagementService.getHubInfo();
    const hubKey = hubInfo.data.hostkey || null;
    if (hubKey == null) {
      throw {
        data: 'Cannot get the Hub key to write needed CMDB data for deployment. ' + 'Please ensure that Hub is reported and re-bootstrap if not.'
      };
    }
    return hubKey;
  },

  clearVCS: function () {
    return this.$http.post('/settingsApi/clearVCS', { cache: false });
  },

  setDefaultAction: function (id, action) {
    return this.$http.post(`${this.MODULE_URL}/defaultAction/${id}`, { action }, { cache: false });
  }
});

(function () {
  const projectsServiceClassProvider = Class.extend({
    instance: new projectsServiceClass(),
    $get: [
      '$http',
      'cmdbService',
      'hubManagementService',
      'actionService',
      function ($http, cmdbService, hubManagementService, actionService) {
        this.instance.$http = $http;
        this.instance.cmdbService = cmdbService;
        this.instance.hubManagementService = hubManagementService;
        this.instance.actionService = actionService;
        return this.instance;
      }
    ]
  });

  angular.module('projectsServiceModule', []).provider('projectsService', projectsServiceClassProvider);
})();
