from flask import jsonify
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy_filters import apply_filters
from database import Phone
import yaml


def filter_phones(criteria):
    """function sets up filter using criteria and then calls the databse with filter and get phones back

    Args:
        criteria (list): list of criteria to filter phones

    Returns:
        list: filtered phones by criteria
    """
    # print(100*"-")
    #print("tisk kriterii")
    # print(criteria)
    # print(100*"-")

    # filtration of data using criteria
    query = Phone.query

    # saving hypotheses data to array
    crt = criteria["hypotheses"]
    hypotheses_together = []
    for hypothese in crt:
        hypotheses_together.append(float(crt["%s" % hypothese]))

    # filtration
    filter_spec = []

    # opening setup file
    with open('filter_setup.yaml') as f:
        fs_new = yaml.load(f, Loader=yaml.FullLoader)

    # filter cycles througth all hypotheses saved in array retyped as float numbers,
    #  for every hypothese there are respective values in setup file filtr_setup_new.yaml
    # parts of database query use sql_alchemy_filters library and they look like:
    # {'field':"name of database column",'op':"operator (>,<,>=,<=,==)",'value': "value in database that will be used to filter"}
    # example:
    # {'field': 'fotoaparat', 'op': '>', 'value': 0.7}
    for x in range(len(hypotheses_together)):
        if(fs_new[x]["filter_type"] == "continuous_range"):  # was 1
            # mapping hypothese to a certain contionuous range
            if(hypotheses_together[x] >= fs_new[x]["criteria_top"]):
                filter_spec.append(
                    dict({'field': '%s' % fs_new[x]['name'], 'op': fs_new[x]["operator_top"], 'value': fs_new[x]["threshold_top"]}))
            elif(hypotheses_together[x] <= fs_new[x]["criteria_bottom"]):
                filter_spec.append(
                    dict({'field': '%s' % fs_new[x]['name'], 'op': fs_new[x]["operator_bottom"], 'value': fs_new[x]["threshold_bottom"]}))
        elif(fs_new[x]["filter_type"] == "two_intervals"):  # was 3
            # mapping hypothese to a certain contionuous range with interval inside a range
            # for upper part of interval
            if (hypotheses_together[x] >= fs_new[x]["criteria_top"]):
                filter_spec.append(
                    dict({'field': '%s' % fs_new[x]['name'], 'op': fs_new[x]["operator_top"], 'value':  fs_new[x]["threshold_top"]}))
            # for lower part of interval
            elif (hypotheses_together[x] <= fs_new[x]["criteria_bottom"]):
                filter_spec.append(
                    dict({'field': '%s' % fs_new[x]['name'], 'op': fs_new[x]["operator_bottom"], 'value':  fs_new[x]["threshold_bottom"]}))
            # for middle part of interval
            elif (((hypotheses_together[x] < fs_new[x]["criteria_top"]) and (hypotheses_together[x] > fs_new[x]["criteria_middle_top"])) or
                  ((hypotheses_together[x] < fs_new[x]["criteria_middle_bottom"]) and (hypotheses_together[x] > fs_new[x]["criteria_bottom"]))):
                filter_spec.append(
                    dict({'field': '%s' % fs_new[x]['name'], 'op': fs_new[x]["operator_mid"], 'value':  fs_new[x]["threshold_middle"]}))
        elif (fs_new[x]["filter_type"] == "logical_mapping"):  # was 2
            # logical mapping of hypotheses
            if(hypotheses_together[x] > fs_new[x]["criteria_top"]):
                filter_spec.append(
                    dict({'field': '%s' % fs_new[x]['name'], 'op': fs_new[x]["operator_top"], 'value':  fs_new[x]["threshold_top"]}))

    # end of filtration
    # print(100*"-")
    # print(filter_spec)
    # print(100*"-")
    # application of filter to database query
    filtered_query = apply_filters(query, filter_spec)
    # executing a database query
    filtered_phones = filtered_query.all()

    return convert(filtered_phones)


def convert(phones):
    """get important informations from database return type

    Args:
        phones (list):list of results of database query

    Returns:
        list: list of dictionaries with information to display on frontend
    """
    phones_list = []
    phone_dict = {'id': '', 'brand': '',
                  'model': '', 'price': '', 'text': '', 'image': '', 'mem': ''}
    for phone in phones:
        phone = phone.__dict__
        phone_dict['id'] = phone['_id']
        phone_dict['brand'] = phone['znacka']
        phone_dict['model'] = phone['model']
        phone_dict['price'] = phone['cena']
        phone_dict['text'] = phone['popis']
        phone_dict['image'] = phone['obrazek']
        phone_dict['mem'] = phone['pamet']
        phones_list.append(dict(phone_dict))
    return phones_list
