import { getValueName } from 'client/Containers/Calculation/Elements/tools';
import initialFilters, {
  autoSetValuesElements,
  noResetValueElements,
} from 'client/stores/CalculationStore/config/initialFilters';
import initialStatuses from 'client/stores/CalculationStore/config/initialStatuses';
import { isNil, mergeWith, pick } from 'lodash';

const valuesData = {
  values: {},
  statuses: initialStatuses,
  validations: {},
  options: {},
  filters: initialFilters,
};

const valuesActions = {
  getValue(sourceValueName) {
    return this.values[sourceValueName];
  },
  getValues(valuesNames) {
    return pick(this.values, valuesNames);
  },
  setValue(sourceValueName, newValue) {
    this.values[sourceValueName] = newValue;
  },
  setValues(values, override) {
    if (override) this.values = values;
    this.values = Object.assign(this.values, values);
  },

  getStatus(elementName) {
    if (this.stores.calculationProcess.bypass.status) {
      const { target, value } = this.stores.calculationProcess.bypass.status;
      if (target.indexOf(elementName) > -1) {
        return value;
      }
    }
    return this.statuses[elementName];
  },
  setStatus(elementName, status) {
    this.statuses[elementName] = status;
  },

  setStatuses(statuses, override) {
    if (override) this.statuses = statuses;
    this.statuses = Object.assign(this.statuses, statuses);
  },

  getValidation(elementName) {
    return this.validations[elementName];
  },
  setValidation(elementName, validation) {
    this.validations[elementName] = validation;
  },

  getOption(elementName, fields) {
    if (!this.options[elementName]) {
      return;
    }
    if (!fields) {
      return this.getCurrentOption(elementName);
    }
    return this.options[elementName].find(option => {
      return Object.keys(fields).every(
        fieldName => option[fieldName] === fields[fieldName],
      );
    });
  },
  getOptions(elementName, fields, filtered = false) {
    let options = this.options[elementName];
    const filter = this.filters[elementName];
    if (filtered && filter) {
      options = filter(options);
    }

    if (!options) {
      return;
    }
    if (!fields) return options;
    return this.options[elementName].filter(option => {
      return Object.keys(fields).every(
        fieldName => option[fieldName] === fields[fieldName],
      );
    });
  },
  getCurrentOption(elementName) {
    const valueName = getValueName(elementName);
    const currentValue = this.values[valueName];
    if (!currentValue) {
      return;
    }
    const currentOption = this.options[elementName].find(
      x => x.value === currentValue,
    );
    return currentOption;
  },
  setOptions(elementName, options) {
    this.options[elementName] = options;
  },
  applyOptions(options) {
    this.options = mergeWith(this.options, options, (obj, src) => {
      if (!isNil(src)) {
        return src;
      }
      return obj;
    });
  },

  getFilter(elementName) {
    return this.filters[elementName];
  },
  setFilter(elementName, filter) {
    const valueName = getValueName(elementName);
    const value = this.getValue(valueName);

    const filteredOptions = filter && filter(this.getOptions(elementName));
    // После установки фильтра проверяем, что значение есть в отфильтрованном списке, иначе сбрасываем значение
    if (
      !filteredOptions?.some(x => x.value === value) &&
      !noResetValueElements.includes(elementName)
    ) {
      this.setValue(valueName, null);
    }

    // После установки фильтра если остается одна запись указываем ее в значение
    if (
      autoSetValuesElements.includes(elementName) &&
      filteredOptions?.length === 1
    ) {
      this.setValue(valueName, filteredOptions[0].value);
    }
    this.filters[elementName] = filter;
  },
  // applyFilters(filters) {
  //   this.filters = { ...this.filters, ...filters };
  // },
};

export default Object.assign(valuesData, valuesActions);
