#!/usr/bin/env python

import os.path
import codecs

import _pathfix

from mhapi.db import MHDB


RANK_NUM = dict(LR=0, HR=1, G=2)
RANK_NAME = ["LR", "HR", "G"]


def get_utf8_writer(writer):
    return codecs.getwriter("utf8")(writer)


def set_quest_ranks(db):
    quests = db.get_quests()
    for quest in quests:
        if not quest["name"]:
            assert quest["hub"] == "Event"
            print("WARN: skipping non localized event quest: %d" % quest.id)
            continue
        set_quest_rank(db, quest)


def set_quest_rank(db, quest):
    quest_id = quest.id
    hub = quest.hub
    stars = quest.stars
    rank_stars_guess = guess_rank(hub, stars)
    if isinstance(rank_stars_guess, tuple):
        rewards = db.get_quest_rewards(quest_id)
        rank = guess_quest_rank_from_rewards(db, rewards)
        if rank is None:
            print("WARN: quest '%s' has no flesh rewards, assuming lower rank"\
                % (quest.name.encode("utf8"),))
            rank = rank_stars_guess[0]
        elif rank not in rank_stars_guess:
            print("ERROR: quest '%s' reward guess '%s' not in stars guess '%s'"\
             % (quest.name, rank, rank_stars_guess))
    else:
        rank = rank_stars_guess

    assert rank in "LR HR G".split()

    quest.rank = rank
    print(quest.one_line_u())
    cur = db.cursor()
    cur.execute("UPDATE quests SET rank=? WHERE _id=?", (rank, quest_id))


def guess_rank(hub, stars):
    if hub == "Caravan":
        # 6 * is actually a mix of LR and HR,
        # and 10 * is mix of HR and G
        if stars < 6:
            return "LR"
        elif stars == 6:
            return ("LR", "HR")
        elif stars == 10:
            return ("HR", "G")
        return "HR"
    if hub in ("Guild", "Event"):
        if stars < 4:
            return "LR"
        elif stars < 8:
            return "HR"
        return "G"
    else:
        raise ValueError("Unknown hub '%s'" % hub)


def guess_quest_rank_from_rewards(db, rewards_rows):
    max_min_rank = RANK_NUM["LR"]
    has_flesh_rewards = False
    for reward in rewards_rows:
        # for each flesh quest reward, see if it's only available from
        # HR or G monsters
        item = db.get_item(reward["item_id"])
        if item["type"] not in ("Flesh", "Sac/Fluid"):
            continue
        has_flesh_rewards = True
        monsters = db.get_item_monsters(reward["item_id"])
        min_rank = 3
        for m in monsters:
            rank = m["rank"]
            if RANK_NUM[rank] < min_rank:
                min_rank = RANK_NUM[rank]
        if min_rank > max_min_rank and min_rank != 3:
            max_min_rank = min_rank
    if not has_flesh_rewards:
        # Can't make useful guess from the rewards
        return None
    return RANK_NAME[max_min_rank]


if __name__ == '__main__':
    from _pathfix import db_path
    db_file = os.path.join(db_path, "mh4u.db")
    db = MHDB(db_file)

    import sys
    sys.stdout = get_utf8_writer(sys.stdout)
    sys.stderr = get_utf8_writer(sys.stderr)
    set_quest_ranks(db)
    db.commit()
    db.close()
