import {DateFilter, NumberFilter, TextFilter} from "ag-grid-community";
import {SetFilter} from "../component/grid/filter/SetFilter";
import {FilterInfo} from "./AuditService";
import {FileAvailableFilterComp} from "../component/grid/filter/FileAvailableFilterComp";

export class FilterService {
  static getFilterData(columnDef: any, agFilter: any): FilterInfo {
    if (!agFilter) {
      return;
    }
    switch (columnDef.filter) {
      case DateFilter:
      case NumberFilter:
        return this.processDateOrNumberFilter(agFilter);
      case SetFilter:
        return this.processSetFilter(agFilter);
      case TextFilter:
        return this.processTextFilter(agFilter);
      case FileAvailableFilterComp:
        return this.processFileAvailableFilter(agFilter);
      default:
        return;
    }
  }

  private static processDateOrNumberFilter(agFilter: any): FilterInfo {
    if (!agFilter.condition1 && !agFilter.condition2) {
      if (agFilter.type === "inRange") {
        return this.createSingleConditionData(
            this.formatFilterValue(agFilter.dateFrom, agFilter.filter, agFilter.filterType),
            agFilter.type,
            this.formatFilterValue(agFilter.dateTo, agFilter.filterTo, agFilter.filterType)
        );
      }
      if (agFilter.type === "blank" || agFilter.type === "notBlank") {
        return this.createSingleConditionData(null, agFilter.type);
      }
      return this.createSingleConditionData(
          this.formatFilterValue(agFilter.dateFrom, agFilter.filter, agFilter.filterType),
          agFilter.type,
      );
    }
    return this.createDualConditionData(agFilter);
  }

  private static processSetFilter(agFilter: any): FilterInfo {
    if (agFilter.value) {
      return this.createSingleConditionData(
          agFilter.value.join(", "),
          "in",
      );
    }
    return;
  }

  private static processTextFilter(agFilter: any): FilterInfo {
    if (!agFilter.condition1 && !agFilter.condition2) {
      if (agFilter.type === "blank" || agFilter.type === "notBlank") {
        return this.createSingleConditionData(null, agFilter.type);
      }
      return this.createSingleConditionData(
          agFilter.filter,
          agFilter.type
      );
    }
    return this.createDualConditionData(agFilter);
  }

  private static processFileAvailableFilter(agFilter: any): FilterInfo {
    const displayValue = agFilter.filter
                         ? "Файл присутствует"
                         : "Файл отсутствует";

    return {
      conditions: [{
        filterValue: displayValue,
        filterType: "equals"
      }]
    };
  }

  private static createSingleConditionData(
      filterValue: string,
      filterType: string,
      endValue?: string
  ): FilterInfo {
    return {
      conditions: [{
        filterValue: endValue ? `${filterValue} to ${endValue}` : filterValue,
        filterType: filterType,
      }]
    };
  }

  private static createDualConditionData(agFilter: any): FilterInfo {
    const condition1 = agFilter.condition1
                       ? {
          filterValue: this.getConditionValue(agFilter.condition1),
          filterType: agFilter.condition1.type,
        }
                       : undefined;

    const condition2 = agFilter.condition2
                       ? {
          filterValue: this.getConditionValue(agFilter.condition2),
          filterType: agFilter.condition2.type,
        }
                       : undefined;

    return {
      conditionOperator: agFilter.operator,
      conditions: [condition1, condition2]
    };
  }

  private static getConditionValue(condition: any): string {
    if (condition.type === "inRange") {
      return `${this.formatFilterValue(condition.dateFrom, condition.filter, condition.filterType)} 
      to ${this.formatFilterValue(condition.dateTo, condition.filterTo, condition.filterType)}`;
    }
    if (condition.type === "blank" || condition.type === "notBlank") {
      return null;
    }
    return this.formatFilterValue(condition.dateFrom, condition.filter, condition.filterType);
  }

  private static formatFilterValue(dateValue: any, defaultValue: any, filterType: string): string {
    if (filterType === "date" && dateValue) {
      return new Date(dateValue).toISOString();
    }
    return defaultValue;
  }

}