// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.

import FauxtonAPI from '../../core/api';
import ActionTypes from './actiontypes';
import Search from './resources';
import Documents from '../documents/base';
import SidebarActions from '../documents/sidebar/actions';
import IndexEditorActions from '../documents/index-editor/actions';
import * as API from './api';

const dispatchInitNewSearchIndex = (params) => {
  // ensure we start with a clear slate
  FauxtonAPI.reduxDispatch({ type: ActionTypes.SEARCH_INDEX_CLEAR });
  FauxtonAPI.reduxDispatch({
    type: ActionTypes.SEARCH_INDEX_SET_LOADING,
    options: {
      loading: true
    }
  });

  params.designDocs.fetch().then(() => {
    FauxtonAPI.reduxDispatch({
      type: ActionTypes.SEARCH_INDEX_DESIGN_DOCS_LOADED,
      options: {
        designDocs: params.designDocs,
        defaultDDoc: params.defaultDDoc,
        database: params.database
      }
    });
  });
};

const dispatchInitSearchIndex = (params)  => {
  FauxtonAPI.reduxDispatch({
    type: ActionTypes.SEARCH_INDEX_SET_LOADING,
    options: {
      loading: true
    }
  });

  FauxtonAPI.reduxDispatch({
    type: ActionTypes.SEARCH_INDEX_INIT,
    options: {
      databaseName: params.databaseName,
      partitionKey: params.partitionKey,
      ddocName: params.designDoc,
      indexName: params.indexName,
      searchQuery: params.query ? params.query : ''
    }
  });

  if (params.query) {
    return executSearchQuery(params.databaseName, params.partitionKey, params.designDoc,
      params.indexName, params.query, FauxtonAPI.reduxDispatch);
  }
};

const dispatchEditSearchIndex = (params) => {
  var ddocInfo = new Documents.DdocInfo({ _id: params.ddocID }, { database: params.database });

  FauxtonAPI.reduxDispatch({
    type: ActionTypes.SEARCH_INDEX_SET_LOADING,
    options: {
      loading: true
    }
  });

  FauxtonAPI.Promise.all([params.designDocs.fetch(), ddocInfo.fetch()]).then(([ddocs]) => {
    const ddoc = ddocs.rows.find(ddoc => ddoc._id === ddocInfo.id).doc;
    if (!ddoc.indexes || !ddoc.indexes[params.indexName]) {
      throw Error(`Index "${params.indexName}" not found`);
    }
    FauxtonAPI.reduxDispatch({
      type: ActionTypes.SEARCH_INDEX_INIT_EDIT_SEARCH_INDEX,
      options: {
        indexName: params.indexName,
        database: params.database,
        ddocInfo: ddocInfo,
        designDocs: params.designDocs
      }
    });
  }).catch(err => {
    const details = err.message ? err.message : '';
    FauxtonAPI.addNotification({
      msg: `There was a problem editing the search index "${params.indexName}". ` + details,
      type: 'error',
      clear: true
    });
  });
};

const selectTab = (tab) => (dispatch) => {
  dispatch({
    type: ActionTypes.SEARCH_INDEX_SELECT_TAB,
    options: {
      tab: tab
    }
  });
};

const setSearchIndexName = (str) => (dispatch) => {
  dispatch({
    type: ActionTypes.SEARCH_INDEX_SET_NAME,
    options: {
      value: str
    }
  });
};

const setAnalyzerType = (type) => (dispatch) => {
  dispatch({
    type: ActionTypes.SEARCH_INDEX_SET_ANALYZER_TYPE,
    options: {
      value: type
    }
  });
};

const addAnalyzerRow = (analyzer) => (dispatch) => {
  dispatch({
    type: ActionTypes.SEARCH_INDEX_ADD_ANALYZER_ROW,
    options: {
      analyzer: analyzer
    }
  });
};

const removeAnalyzerRow = (rowIndex) => (dispatch) => {
  dispatch({
    type: ActionTypes.SEARCH_INDEX_REMOVE_ANALYZER_ROW,
    options: {
      rowIndex: rowIndex
    }
  });
};

const setAnalyzerRowFieldName = (params) => (dispatch) => {
  dispatch({
    type: ActionTypes.SEARCH_INDEX_SET_ANALYZER_ROW_FIELD_NAME,
    options: {
      rowIndex: params.rowIndex,
      fieldName: params.fieldName
    }
  });
};

const setAnalyzer = (params) => (dispatch) => {
  dispatch({
    type: ActionTypes.SEARCH_INDEX_SET_ANALYZER_ROW,
    options: {
      rowIndex: params.rowIndex,
      analyzer: params.analyzer
    }
  });
};

const setDefaultMultipleAnalyzer = (analyzer) => (dispatch) => {
  dispatch({
    type: ActionTypes.SEARCH_INDEX_SET_DEFAULT_MULTIPLE_ANALYZER,
    options: {
      analyzer: analyzer
    }
  });
};

const setSingleAnalyzer = (analyzer) => (dispatch) => {
  dispatch({
    type: ActionTypes.SEARCH_INDEX_SET_SINGLE_ANALYZER,
    options: {
      analyzer: analyzer
    }
  });
};

const saveSearchIndex = (doc, info, navigateToUrl) => {
  doc.setIndex(info.indexName, info.indexFunction, info.analyzerInfo);

  if (info.lastSavedDesignDocName === doc.id && info.lastSavedSearchIndexName !== info.indexName) {
    var indexes = doc.get('indexes') || {};
    delete indexes[info.lastSavedSearchIndexName];
    doc.set({ indexes: indexes });
  }

  doc.save().then(() => {
    info.designDocs.add(doc, { merge: true });

    FauxtonAPI.addNotification({
      msg: 'The search index has been saved.',
      type: 'success',
      clear: true
    });

    // if the user just saved the view to a different design doc, remove the view from the old design doc and
    // maybe even delete if it's empty
    if (!info.isCreatingIndex && info.lastSavedDesignDocName !== doc.id) {
      const oldDesignDoc = IndexEditorActions.helpers.findDesignDoc(info.designDocs, info.lastSavedDesignDocName);
      IndexEditorActions.safeDeleteIndex(oldDesignDoc, info.designDocs, 'indexes', info.lastSavedSearchIndexName, {
        onSuccess: () => {
          SidebarActions.dispatchUpdateDesignDocs(info.designDocs);
        }
      });
    }

    SidebarActions.dispatchUpdateDesignDocs(info.designDocs);
    FauxtonAPI.navigate(navigateToUrl, { trigger: true });
  }, (xhr) => {
    const responseText = JSON.parse(xhr.responseText).reason;
    FauxtonAPI.addNotification({
      msg: 'Save failed: ' + responseText,
      type: 'error',
      clear: true
    });
  });
};


const deleteSearchIndex = (options) => {
  const onSuccess = () => {

    // if the user was on the index that was just deleted, redirect them back to all docs
    if (options.isOnIndex) {
      const url = FauxtonAPI.urls('allDocs', 'app', options.database.safeID());
      FauxtonAPI.navigate(url);
    }
    SidebarActions.dispatchUpdateDesignDocs(options.designDocs);

    FauxtonAPI.addNotification({
      msg: 'The <code>' + _.escape(options.indexName) + '</code> search index has been deleted.',
      type: 'info',
      escape: false,
      clear: true
    });
    SidebarActions.dispatchHideDeleteIndexModal();
  };

  IndexEditorActions.safeDeleteIndex(options.designDoc, options.designDocs, 'indexes', options.indexName, { onSuccess });
};

const cloneSearchIndex = (params) => {
  const targetDesignDoc = getDesignDoc(params.designDocs, params.targetDesignDocName, params.newDesignDocName, params.database);
  let indexes = targetDesignDoc.get('indexes');
  if (indexes && _.has(indexes, params.newIndexName)) {
    FauxtonAPI.addNotification({
      msg: 'That index name is already used in this design doc. Please enter a new name.',
      type: 'error',
      clear: true
    });
    return;
  }
  if (!indexes) {
    indexes = {};
  }
  const sourceDesignDoc = IndexEditorActions.helpers.findDesignDoc(params.designDocs, '_design/' + params.sourceDesignDocName);
  const sourceDesignDocJSON = sourceDesignDoc.toJSON();

  // this sets whatever content is in the source index into the target design doc under the new index name
  indexes[params.newIndexName] = sourceDesignDocJSON.indexes[params.sourceIndexName];
  targetDesignDoc.set({ indexes: indexes });

  targetDesignDoc.save().then(function () {
    params.onComplete();
    FauxtonAPI.addNotification({
      msg: 'The search index has been cloned.',
      type: 'success',
      clear: true
    });

    SidebarActions.dispatchUpdateDesignDocs(params.designDocs);
  },
  function (xhr) {
    params.onComplete();
    var responseText = JSON.parse(xhr.responseText).reason;
    FauxtonAPI.addNotification({
      msg: 'Clone failed: ' + responseText,
      type: 'error',
      clear: true
    });
  });
};

const gotoEditSearchIndexPage = (databaseName, partitionKey, designDocName, indexName) => {
  const encodedPartKey = partitionKey ? encodeURIComponent(partitionKey) : '';
  FauxtonAPI.navigate('#' + FauxtonAPI.urls('search', 'edit', encodeURIComponent(databaseName),
    encodedPartKey, encodeURIComponent(designDocName), encodeURIComponent(indexName)));
};

const selectDesignDoc = (designDoc) => (dispatch) => {
  dispatch({
    type: ActionTypes.SEARCH_INDEX_SELECT_DESIGN_DOC,
    options: {
      value: designDoc
    }
  });
};

// const querySearch = (searchQuery, partitionKey) => {
const querySearch = (databaseName, partitionKey, ddocName, indexName, searchQuery) => {
  const encodedDatabaseName = encodeURIComponent(databaseName);
  const encodedPartitionKey = encodeURIComponent(partitionKey);
  const encodedDdocName = encodeURIComponent(ddocName);
  const encodedIndexName = encodeURIComponent(indexName);
  const encodedSearchQuery = encodeURIComponent(searchQuery);

  const baseUrl = partitionKey ?
    FauxtonAPI.urls('partitioned_search', 'app', encodedDatabaseName, encodedPartitionKey, encodedDdocName, encodedIndexName) :
    FauxtonAPI.urls('search', 'app', encodedDatabaseName, encodedDdocName, encodedIndexName);
  FauxtonAPI.navigate(`${baseUrl}${encodedIndexName}?${encodedSearchQuery}`, {trigger: true});
};

const executSearchQuery = (database, partitionKey, ddoc, index, searchQuery, dispatch) => {
  dispatch({ type: ActionTypes.SEARCH_INDEX_PREVIEW_REQUEST_MADE });

  return API.fetchSearchResults(database, partitionKey, ddoc, index, searchQuery)
    .then(rows => {
      dispatch({
        type: ActionTypes.SEARCH_INDEX_PREVIEW_MODEL_UPDATED,
        options: {
          searchResults: rows
        }
      });
    }).catch(err => {
      dispatch({ type: ActionTypes.SEARCH_INDEX_PREVIEW_REQUEST_ERROR });

      if (err && err.message.includes('`partition` not supported')) {
        dispatch(partitionParamNotSupported());
      } else if (err && err.message.includes('`partition` parameter is mandatory')) {
        dispatch(partitionParamIsMandatory());
      } else {
        FauxtonAPI.addNotification({
          msg: 'Search failed: ' + err.message,
          type: 'error',
          clear: true
        });
      }

      if (err.message.includes('not found')) {
        FauxtonAPI.navigate(FauxtonAPI.urls('allDocsSanitized', 'app', database), {trigger: true});
      }
    });
};

const setSearchQuery = (query) => (dispatch) => {
  dispatch({
    type: ActionTypes.SEARCH_INDEX_SET_SEARCH_QUERY,
    options: {
      query: query
    }
  });
};

const updateNewDesignDocName = (designDocName) => (dispatch) => {
  dispatch({
    type: ActionTypes.SEARCH_INDEX_NEW_DESIGN_DOC_NAME_UPDATED,
    options: {
      value: designDocName
    }
  });
};

const updateNewDesignDocPartitioned = (isPartitioned) => (dispatch) => {
  dispatch({
    type: ActionTypes.SEARCH_INDEX_NEW_DESIGN_DOC_PARTITONED_UPDATED,
    options: {
      value: isPartitioned
    }
  });
};

const partitionParamNotSupported = () => ({
  type: ActionTypes.SEARCH_INDEX_PARTITION_PARAM_NOT_SUPPORTED
});

const partitionParamIsMandatory = () => ({
  type: ActionTypes.SEARCH_INDEX_PARTITION_PARAM_MANDATORY
});


// helpers

function getDesignDoc (designDocs, targetDesignDocName, newDesignDocName, database) {
  if (targetDesignDocName === 'new-doc') {
    var doc = {
      "_id": "_design/" + newDesignDocName,
      "indexes": {},
      "language": "javascript"
    };
    return new Search.Doc(doc, { database: database });
  }

  var foundDoc = designDocs.find(function (ddoc) {
    return ddoc.id === targetDesignDocName;
  });
  return (!foundDoc) ? null : foundDoc.dDocModel();
}


export default {
  dispatchInitNewSearchIndex,
  dispatchInitSearchIndex,
  dispatchEditSearchIndex,
  selectTab,
  setSearchIndexName,
  setAnalyzerType,
  addAnalyzerRow,
  removeAnalyzerRow,
  setAnalyzerRowFieldName,
  setAnalyzer,
  setDefaultMultipleAnalyzer,
  selectDesignDoc,
  saveSearchIndex,
  cloneSearchIndex,
  deleteSearchIndex,
  gotoEditSearchIndexPage,
  querySearch,
  setSearchQuery,
  setSingleAnalyzer,
  updateNewDesignDocName,
  updateNewDesignDocPartitioned,
  partitionParamNotSupported,
  partitionParamIsMandatory
};
