const { currentSearchRequest } = require("../helpers/url");
const { AD_CATEGORY, AD_TYPE, ACCESS_ROAD_TYPE } = require("../common/enums");
const {
  ADVANCED_BOOLEAN_FILTERS,
  ADVANCED_SEGMENT_SELECT_FILTERS,
  ADVANCED_RANGE_FILTERS
} = require("../common/filterEnums");

const getFilters = async (req, res) => {
  const searchRequest = await currentSearchRequest(req);

  if (!searchRequest || !searchRequest.dataValues) {
    res.render("notFound", { title: " " });
    return;
  }

  const title = "Filteri za pretraživanje";

  const {
    adType,
    realEstateType,
    priceMin,
    priceMax,
    sizeMin,
    sizeMax,
    gardenSizeMin,
    gardenSizeMax,
    numberOfRoomsMin,
    numberOfRoomsMax,
    numberOfFloorsMin,
    numberOfFloorsMax,
    floorMin,
    floorMax,
    includeIncompleteAds,
    balcony,
    elevator,
    newBuilding,
    accessRoadType,
    includeWithoutPrice
  } = searchRequest;
  const category = AD_CATEGORY[realEstateType] || AD_CATEGORY.FLAT;

  const {
    hasGardenSize,
    priceSliderOptionsSale,
    priceSliderOptionsRent,
    sizeSliderOptions,
    gardenSizeSliderOptions
  } = category;

  let priceSliderOptions;
  if (adType === AD_TYPE.AD_TYPE_SALE.stringId) {
    priceSliderOptions = Object.assign({}, priceSliderOptionsSale);
  } else if (adType === AD_TYPE.AD_TYPE_RENT.stringId) {
    priceSliderOptions = Object.assign({}, priceSliderOptionsRent);
  } else {
    res.render("notFound", { title: " " });
    return;
  }

  // TODO: Maybe this is slow, pay attention to this
  const filterFilters = filterObject => {
    const filterCategories = filterObject.categoriesToShow;
    return filterCategories.indexOf(category) !== -1;
  };

  const advancedBooleanFilterObjects = ADVANCED_BOOLEAN_FILTERS.filter(
    filterFilters
  );
  const advancedSegmentSelectFilterObjects = ADVANCED_SEGMENT_SELECT_FILTERS.filter(
    filterFilters
  );
  const advancedRangeFilterObjects = ADVANCED_RANGE_FILTERS.filter(
    filterFilters
  );

  const advancedBooleanFilterValues = {
    includeIncompleteAds,
    balcony,
    elevator,
    newBuilding
  };
  const advancedSegmentSelectFilterValues = {
    accessRoadType
  };
  const advancedRangeFilterValues = {
    numberOfFloorsMin,
    numberOfFloorsMax,
    numberOfRoomsMin,
    numberOfRoomsMax,
    floorMin,
    floorMax
  };

  if (priceMin || priceMax) {
    priceSliderOptions.start = [priceMin, priceMax];
  }

  if (sizeMin || sizeMax) {
    sizeSliderOptions.start = [sizeMin, sizeMax];
  }

  if (gardenSizeSliderOptions && (gardenSizeMin || gardenSizeMax)) {
    gardenSizeSliderOptions.start = [gardenSizeMin, gardenSizeMax];
  }

  res.render("realEstateFilters", {
    title,
    hasGardenSize,
    priceSliderOptions: JSON.stringify(priceSliderOptions),
    sizeSliderOptions: JSON.stringify(sizeSliderOptions),
    gardenSizeSliderOptions: JSON.stringify(gardenSizeSliderOptions),
    advancedBooleanFilterObjects,
    advancedBooleanFilterValues,
    advancedSegmentSelectFilterObjects,
    advancedSegmentSelectFilterValues,
    advancedRangeFilterObjects,
    advancedRangeFilterValues,
    includeIncompleteAds,
    includeWithoutPrice
  });
};

const postFilters = async (req, res) => {
  const searchRequest = await currentSearchRequest(req);

  if (!searchRequest || !searchRequest.dataValues) {
    res.render("notFound", { title: " " });
    return;
  }

  const nextStepPage = req.query.nextStep || "pregled";
  const nextStepUrl = `/${nextStepPage}/${searchRequest.id}`;

  const priceMin = parseInt(req.body.priceMin) || 0;
  const priceMax = parseInt(req.body.priceMax) || 0;
  const sizeMin = parseInt(req.body.sizeMin) || 0;
  const sizeMax = parseInt(req.body.sizeMax) || 0;

  const advancedRangeFilters = {};

  ADVANCED_RANGE_FILTERS.forEach(filter => {
    let parsingFunction = parseInt;
    if (filter.decimalPlaces) {
      parsingFunction = parseFloat;
    }

    advancedRangeFilters[filter.dbFieldMin] = parsingFunction(
      req.body[filter.dbFieldMin]
    );
    advancedRangeFilters[filter.dbFieldMax] = parsingFunction(
      req.body[filter.dbFieldMax]
    );

    advancedRangeFilters[filter.dbFieldMin] = isNaN(
      advancedRangeFilters[filter.dbFieldMin]
    )
      ? null
      : advancedRangeFilters[filter.dbFieldMin];
    advancedRangeFilters[filter.dbFieldMax] = isNaN(
      advancedRangeFilters[filter.dbFieldMax]
    )
      ? null
      : advancedRangeFilters[filter.dbFieldMax];

    try {
      if (filter.decimalPlaces) {
        advancedRangeFilters[filter.dbFieldMin] = advancedRangeFilters[
          filter.dbFieldMin
        ].toFixed(filter.decimalPlaces);
        advancedRangeFilters[filter.dbFieldMax] = advancedRangeFilters[
          filter.dbFieldMax
        ].toFixed(filter.decimalPlaces);
      }
    } catch (e) {
      advancedRangeFilters[filter.dbFieldMin] = null;
      advancedRangeFilters[filter.dbFieldMax] = null;
    }

    if (
      advancedRangeFilters[filter.dbFieldMin] < filter.validValueMin ||
      advancedRangeFilters[filter.dbFieldMin] > filter.validValueMax
    ) {
      advancedRangeFilters[filter.dbFieldMin] = filter.validValueMin;
    }

    if (
      advancedRangeFilters[filter.dbFieldMax] < filter.validValueMin ||
      advancedRangeFilters[filter.dbFieldMax] > filter.validValueMax
    ) {
      advancedRangeFilters[filter.dbFieldMax] = filter.validValueMax;
    }
  });

  const includeIncompleteAds = req.body.includeIncompleteAds === "on";
  const includeWithoutPrice = req.body.includeWithoutPrice === "on";

  const balcony = req.body.balcony === "on";
  const elevator = req.body.elevator === "on";
  const newBuilding = req.body.newBuilding === "on";

  const accessRoadType = req.body.accessRoadType;
  if (!ACCESS_ROAD_TYPE[accessRoadType]) {
    res.render("notFound", { title: " Greška !" });
    return;
  }

  //TODO: Filter validation
  searchRequest.priceMin = priceMin;
  searchRequest.priceMax = priceMax;
  searchRequest.sizeMin = sizeMin;
  searchRequest.sizeMax = sizeMax;

  for (const filter of Object.keys(advancedRangeFilters)) {
    searchRequest[filter] = advancedRangeFilters[filter];
  }

  searchRequest.balcony = balcony;
  searchRequest.elevator = elevator;
  searchRequest.newBuilding = newBuilding;

  searchRequest.includeIncompleteAds = includeIncompleteAds;
  searchRequest.includeWithoutPrice = includeWithoutPrice;

  searchRequest.accessRoadType = accessRoadType;

  if (
    req.body.gardenSizeMin !== undefined &&
    req.body.gardenSizeMax !== undefined
  ) {
    const gardenSizeMin = parseInt(req.body.gardenSizeMin);
    const gardenSizeMax = parseInt(req.body.gardenSizeMax);

    //TODO: Filter validation

    searchRequest.gardenSizeMin = gardenSizeMin;
    searchRequest.gardenSizeMax = gardenSizeMax;
  }
  await searchRequest.save();

  res.redirect(nextStepUrl);
};

module.exports = {
  getFilters,
  postFilters
};
