import time
import random
import urllib.parse
import HelperFunctions
import Conversions
import FilterSkins
import concurrent.futures
import threading
import queue
import DBStuff
# from sniper.models import cs2snipe_found

lock = threading.Lock()
all_done = threading.Event()


# {'weapon_name': 'tag_weapon_knife_flip', 'skin_or_weapon': 'weapon', 'stat': 'stat_only', 'filter_options': 'other_filter', 'condition': 'Factory New', 'more_filters': ['rank'], 'rank': 1, 'pages': 2, 'question1': ['Item 1']}
# {'weapon_name': 'tag_weapon_ak47', 'skin_or_weapon': 'weapon', 'stat': 'stat_and_non_stat', 'filter_options': 'exact_float', 'exact_float': 0.499945, 'more_filters': ['rank', 'pattern', 'price'], 'rank': 1, 'pattern': 2, 'price': 3, 'pages': 4, 'question1': ['Item 1']}

# {'weapon_name': 'tag_weapon_famas', 'skin_or_weapon': 'weapon', 'stat': 'stat_only', 'filter_options': 'float_restrictions', 'float_restrictions': 'starts_with', 'float_for_restriction': 0.1, 'more_filters': ['rank'], 'rank': 1, 'pages': 1, 'question1': ['Item 1']}
# {'weapon_name': 'tag_weapon_knife_flip', 'skin_or_weapon': 'weapon', 'stat': 'stat_and_non_stat', 'filter_options': 'float_restrictions', 'float_restrictions': 'is_bigger', 'float_for_restriction': 0.1, 'more_filters': ['price'], 'price': 1, 'pages': 1, 'question1': ['Item 1']}
# {'weapon_name': 'tag_weapon_knife_falchion', 'skin_or_weapon': 'weapon', 'stat': 'stat_and_non_stat', 'filter_options': 'float_restrictions', 'float_restrictions': 'is_smaller', 'float_for_restriction': 0.1, 'more_filters': ['rank'], 'rank': 1, 'pages': 2, 'question1': ['Item 1']}

# {'weapon_name': 'tag_weapon_galilar', 'skin_or_weapon': 'weapon', 'stat': 'stat_only', 'filter_options': 'other_filter', 'more_filters': ['rank', 'pattern', 'price'], 'condition': 'Battle-Scarred', 'rank': 1, 'pattern': 2, 'price': 3, 'pages': 1, 'question1': ['Item 1']}

# {'skin_or_weapon': 'skin', 'stat': 'stat_only', 'skin_name': 'AK-47 | Nighwish', 'filter_options': 'other_filter', 'condition': 'Factory New', 'more_filters': ['rank'], 'rank': 1, 'pages': 2, 'question1': ['Item 1']}


def startFiltering(
    result_json,
    inspect_server_url,
    ReqManager,
    steamid,
    queryid,
    filterthread_done: threading.Event,
    inspect_link_queue: queue.Queue,
):
    while True:
        # if all_done.is_set():
        #     return None
        while inspect_link_queue.qsize() != 0:
            inspect_link_list = inspect_link_queue.get()
            print("Got Queue item")

            FilterSkins.filterSkins(
                result_json,
                inspect_link_list,
                inspect_server_url,
                ReqManager,
                steamid,
                queryid,
            )
        time.sleep(random.uniform(0.3, 1.6))
        if all_done.is_set():
            filterthread_done.set()
            return None


def findWeapon(result_json, steamid, queryid, ReqManager):
    all_done.clear()
    # filterthreads_done.clear()
    inspect_server_url = "http://23.88.122.57:1337/"
    weapon_listings_url_list = getHashedNameListHighOrLow(result_json, ReqManager)

    inspect_link_queue = queue.Queue()

    thread_events = []
    for i in range(5):
        filterthread_done = threading.Event()
        t = threading.Thread(
            target=startFiltering,
            args=(
                result_json,
                inspect_server_url,
                ReqManager,
                steamid,
                queryid,
                filterthread_done,
                inspect_link_queue,
            ),
        )
        # t.daemon = True
        thread_events.append(filterthread_done)
        t.start()

    with concurrent.futures.ThreadPoolExecutor(max_workers=20) as executor:
        futures = []
        for url in weapon_listings_url_list:
            futures.append(
                executor.submit(
                    HelperFunctions.singleBuildInspectList,
                    result_json=result_json,
                    listing=url,
                    ReqManager=ReqManager,
                )
            )

        for future in concurrent.futures.as_completed(futures):
            with lock:
                inspect_link_queue.put(future.result())
    all_done.set()

    if all_done.is_set():
        for event in thread_events:
            event.wait()
        query_results = DBStuff.getResultCount(queryid, steamid)
        if query_results == 0:
            query_message = "No matching skins found."
        else:
            query_message = str(query_results) + " matching skins found."
        DBStuff.updateQuery(queryid, False, "Done", query_message)
        print("Done with " + str(result_json))
    for event in thread_events:
        event.clear()
    return None

def getHashedNameListHighOrLow(result_json, ReqManager):
    if result_json["filter_options"] == "other_filter":
        wear = Conversions.conditionToWearConversion(result_json["condition_wep"])
    if result_json["filter_options"] == "exact_float":
        wear = Conversions.floatToWearConversion(result_json["exact_float"])

    if result_json["filter_options"] == "float_restrictions":
        wear = Conversions.floatToWearConversion(result_json["float_for_restriction"])
    if isinstance(wear, list):
        wears = wear
    else:
        wears = [wear]
    # print(wear)

    weapon_type = Conversions.typeToURLPart(
        result_json["type"], result_json["weapon_name"]
    )
    #####stat only
    # https://steamcommunity.com/market/search?q=&category_730_ItemSet%5B%5D=any&category_730_ProPlayer%5B%5D=any&category_730_StickerCapsule%5B%5D=any&category_730_TournamentTeam%5B%5D=any&category_730_Weapon%5B%5D=any&category_730_Quality%5B%5D=tag_strange&appid=730
    #####souv only
    # https://steamcommunity.com/market/search?q=&category_730_ItemSet%5B%5D=any&category_730_ProPlayer%5B%5D=any&category_730_StickerCapsule%5B%5D=any&category_730_TournamentTeam%5B%5D=any&category_730_Weapon%5B%5D=any&category_730_Quality%5B%5D=tag_tournament&appid=730
    #####stat and non stat
    # https://steamcommunity.com/market/search?q=&category_730_ItemSet%5B%5D=any&category_730_ProPlayer%5B%5D=any&category_730_StickerCapsule%5B%5D=any&category_730_TournamentTeam%5B%5D=any&category_730_Weapon%5B%5D=any&category_730_Quality%5B%5D=tag_normal&category_730_Quality%5B%5D=tag_strange&appid=730
    #####all
    # https://steamcommunity.com/market/search?q=&category_730_ItemSet%5B%5D=any&category_730_ProPlayer%5B%5D=any&category_730_StickerCapsule%5B%5D=any&category_730_TournamentTeam%5B%5D=any&category_730_Weapon%5B%5D=any&appid=730
    # https://steamcommunity.com/market/search?q=&category_730_ItemSet%5B%5D=any&category_730_ProPlayer%5B%5D=any&category_730_StickerCapsule%5B%5D=any&category_730_TournamentTeam%5B%5D=any&category_730_Weapon%5B%5D=any&category_730_Exterior%5B%5D=tag_WearCategory2&category_730_Quality%5B%5D=tag_tournament&appid=730
    #####GLOVES????
    # https://steamcommunity.com/market/search?category_730_Type%5B0%5D=tag_Type_Hands&appid=730
    # https://steamcommunity.com/market/search/render?currency=3&norender=1/?query=&start=0&count=100&search_descriptions=0&sort_column=price&sort_dir=asc&appid=730&category_730_ItemSet%5B%5D=any&category_730_ProPlayer%5B%5D=any&category_730_StickerCapsule%5B%5D=any&category_730_TournamentTeam%5B%5D=any&category_730_Type%5B0%5D=tag_Type_Hands&category_730_Quality%5B%5D=0&appid=730

    ####GLOVES!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    # https://steamcommunity.com/market/search/render?currency=3&norender=1/?query=&start=0&count=100&search_descriptions=0&sort_column=price&sort_dir=asc&appid=730&category_730_ItemSet%5B%5D=any&category_730_ProPlayer%5B%5D=any&category_730_StickerCapsule%5B%5D=any&category_730_TournamentTeam%5B%5D=any&category_730_Type%5B0%5D=tag_Type_Hands&category_730_Quality%5B%5D=0&appid=730

    start = 0
    end = False
    weapon_listings_url_list = []

    while not end:
        for wear in wears:
            if result_json["weapon_name"] == "gloves":
                all_skins_url = (
                    "https://steamcommunity.com/market/search/render?currency=3&norender=1/?query=&start="
                    + str(start)
                    + "&count=100&search_descriptions=0&sort_column=price&sort_dir=asc&appid=730&category_730_ItemSet%5B%5D=any&category_730_ProPlayer%5B%5D=any&category_730_StickerCapsule%5B%5D=any&category_730_TournamentTeam%5B%5D=any&category_730_Type%5B0%5D=tag_Type_Hands&category_730_Exterior%5B%5D=tag_WearCategory"
                    + str(wear)
                    + "&category_730_Quality%5B%5D=0&appid=730"
                )

            else:
                all_skins_url = (
                    "https://steamcommunity.com/market/search/render?currency=3&norender=1/?query=&start="
                    + str(start)
                    + "&count=100&search_descriptions=0&sort_column=price&sort_dir=asc&appid=730&category_730_ItemSet%5B%5D=any&category_730_ProPlayer%5B%5D=any&category_730_StickerCapsule%5B%5D=any&category_730_TournamentTeam%5B%5D=any&category_730_Weapon%5B%5D="
                    + str(result_json["weapon_name"])
                    + "&category_730_Exterior%5B%5D=tag_WearCategory"
                    + str(wear)
                    + "&category_730_Quality%5B%5D="
                    + str(weapon_type)
                    + "&appid=730"
                )

            get_alternator = 1
            get_counter = 0
            while True:
                get_alternator = (get_alternator + 1) % 3
                get_counter += 1
                if get_counter > 20:
                    print("Couldn't get page for 20 times: " + str(all_skins_url))
                    return []
                response = ReqManager.getRequest(all_skins_url, get_alternator)
                response_json = HelperFunctions.validateResponseHashedNameList(
                    response=response
                )
                if response_json is None:
                    print("Response Validation failed, trying again.")
                    time.sleep(random.uniform(1, 2))
                    continue
                break

            if start + 100 >= response_json["total_count"]:
                end = True

            if response_json["total_count"] <= 100:
                end = True
            else:
                start += 100

            for result in response_json["results"]:
                listings_url = (
                    "https://steamcommunity.com/market/listings/730/"
                    + urllib.parse.quote(str(result["hash_name"]).encode("utf-8"))
                    + "/render/?query="
                )
                weapon_listings_url_list.append(listings_url)
    return weapon_listings_url_list
