import axios from '@/axios-client.js';
import mapService from '@/services/map-service';


const map = {
  namespaced: true,
  state: {
    map: null,
    basemaps: null,
    basemapsToDelete: [],
    features: [],
    geojsonFeatures: null,
    availableLayers: null,
  },
  mutations: {
    SET_MAP(state, payload) {
      state.map = payload;
    },
    SET_LAYERS(state, availableLayers) {
      state.availableLayers = availableLayers;
    },
    SET_GEOJSON_FEATURES(state, geojsonFeatures) {
      state.geojsonFeatures = geojsonFeatures;
    },
    SET_BASEMAPS(state, basemaps) {
      state.basemaps = basemaps;
    },
    CREATE_BASEMAP(state, id) {
      state.basemaps = [...state.basemaps, { id, title: '', layers: [], errors: [] }];
    },
    UPDATE_BASEMAPS(state, basemaps) {
      state.basemaps = basemaps;
    },
    UPDATE_BASEMAP(state, { title, id, layers, errors }) {
      const index = state.basemaps.findIndex((el) => el.id === id);
      if (index !== -1) {
        state.basemaps[index].title = title;
        state.basemaps[index].errors = errors;
        if (layers) {
          state.basemaps[index].layers = layers;
        }
      }
    },
    DELETE_BASEMAP(state, basemapId) {
      state.basemaps = state.basemaps.filter(el => el.id !== basemapId);
      state.basemapsToDelete.push(basemapId);
    },
    REMOVE_BASEMAP_ID_TO_DELETE(state, basemapId) {
      state.basemapsToDelete = state.basemapsToDelete.filter(el => el !== basemapId);
    },
    REPLACE_BASEMAP_LAYERS(state, { basemapId, layers }) {
      const index = state.basemaps.findIndex((el) => el.id === basemapId);
      if (index !== -1) {
        state.basemaps[index].layers = layers;
      }
    },
    DELETE_BASEMAP_LAYER(state, { basemapId, layerId }) {
      const index = state.basemaps.findIndex((el) => el.id === basemapId);
      if (index !== -1) {
        state.basemaps[index].layers = state.basemaps[index].layers.filter((el) => el.dataKey !== layerId);
      }
    },
    UPDATE_BASEMAP_LAYER(state, { basemapId, layerId, layer }) {
      const index = state.basemaps.findIndex((el) => el.id === basemapId);
      if (index !== -1) {
        state.basemaps[index].layers = state.basemaps[index].layers.map(
          (el) => el.dataKey === layerId ? layer : el
        );
      }
    },
  },

  getters: {
    basemapMaxId: (state) => state.basemaps.reduce((acc, curr) => {
      if (curr.id > acc) {
        return curr.id;
      } else {
        return acc;
      }
    }, 0)
  },

  actions: {
    GET_AVAILABLE_LAYERS({ commit }) {
      return axios
        .get(`${this.state.configuration.VUE_APP_DJANGO_API_BASE}v2/layers/`)
        .then((response) => (commit('SET_LAYERS', response.data)))
        .catch((error) => {
          throw error;
        });
    },

    GET_BASEMAPS({ commit }, project_slug) {
      return axios
        .get(`${this.state.configuration.VUE_APP_DJANGO_API_BASE}v2/base-maps/?project__slug=${project_slug}`)
        .then((response) => {
          if (response.status === 200 && response.data) {
            commit('SET_BASEMAPS', response.data);
          }
          return response;
        })
        .catch((error) => {
          throw error;
        });
    },

    INITIATE_MAP({ commit, rootState }, options) {
      mapService.createMap(options.el, {
        mapDefaultViewZoom: options.zoom || 5,
        mapDefaultViewCenter: options.center || [46, 2],
        maxZoom: options.maxZoom || rootState.projects.project.map_max_zoom_level,
        controls: options.controls,
        zoomControl: options.zoomControl,
        interactions : { doubleClickZoom :false, mouseWheelZoom:true, dragPan:true }
      });
      const map = { ...mapService.getMap() };
      commit('SET_MAP', map);
      mapService.addLayers(
        options.layersToLoad,
        this.state.configuration.DEFAULT_BASE_MAP_SERVICE,
        this.state.configuration.DEFAULT_BASE_MAP_OPTIONS,
        this.state.configuration.DEFAULT_BASE_MAP_SCHEMA_TYPE,
      );
    },

    async SAVE_BASEMAPS({ state, rootState, dispatch }, newBasemapIds) {
      //* send new basemaps synchronously to create their ids in the order they were created in the form
      let promisesResult = [];
      function postOrPut(basemapsToSend) {
        if (basemapsToSend.length > 0) {
          let basemap = basemapsToSend.shift(); //* remove and return first item in array
          basemap['project'] = rootState.projects.project.slug;
          let url = `${rootState.configuration.VUE_APP_DJANGO_API_BASE}base-maps/`;
          if (!newBasemapIds.includes(basemap.id)) url += `${basemap.id}/`;
          promisesResult.push(
            axios({
              url,
              method: newBasemapIds.includes(basemap.id) ? 'POST' : 'PUT',
              data: basemap,
            })
              .then((response) => {
                postOrPut(basemapsToSend);
                return response;
              })
              .catch((error) => {
                postOrPut(basemapsToSend);
                return error;
              })
          );
        }
      }

      function deleteBMap(basemapId) {
        //* delete in the backend the basemaps that was rewoved from the front
        return dispatch('DELETE_BASEMAP', basemapId)
          .then((response) => response);
      }

      postOrPut([...state.basemaps]);
      //* delete basemaps
      const deletedResult = await Promise.all(state.basemapsToDelete.map((basemapId) => deleteBMap(basemapId)));
      state.basemapsToDelete = [];
      return [...promisesResult, ...deletedResult];
    },

    DELETE_BASEMAP({ commit }, basemapId) {
      const url = `${this.state.configuration.VUE_APP_DJANGO_API_BASE}base-maps/` + basemapId;
      return axios
        .delete(url)
        .then((response) => {
          if (response && response.status === 204) {
            commit('REMOVE_BASEMAP_ID_TO_DELETE', basemapId);
            return response;
          }
        })
        .catch((error) => {
          console.error(error);
          return error;
        });
    }
  },
};
export default map;