# -*- coding: utf-8 -*-
"""
Generate readable HTML table for comparing estimates.

AUTHOR:

    Fernando Virdia - 2018

"""


from math import log, ceil
from cost_asymptotics import BKZ_COST_ASYMPTOTICS
from inspect import getsource
from string import lower
import json

try:
    from config import JSONPATH
except ImportError:
    JSONPATH = "docs/res/full_table.js"


def generate_costs_json():
    """ Generates a JSON string from the BKZ_COST_ASYMPTOTICS list.

    :returns:   the generated string
    """
    models = []
    for model in BKZ_COST_ASYMPTOTICS:
        models += [{
            "name": model["name"],
            "lambda": "%s"%getsource(model["reduction_cost_model"]).split('":')[1][:-2],
            "human": model["human_friendly"],
            "group": model["group"]
        }]
    return json.dumps(models)

def generate_table_json(estimates_list):
    """ Generates a JSON string from the estimates list.

    :params estimates_list:         list of estimates generated by estimates.py
    :returns:                       the generated string
    """

    def sanitise_param(scheme):
        """ Given a Sagemath object, it sanitises its entries for enabling JSON
            dumping.

        :returns:           the sanitised object
        """
        for i in range(len(scheme["param"])):
            params = scheme["param"][i]
            # sanitise secret_distribution
            secret_distribution = False
            if "secret_distribution" in params:
                secret_distribution = params["secret_distribution"]
                if type(secret_distribution) != str:
                    if type(secret_distribution[0]) == tuple:
                        a = int(secret_distribution[0][0])
                        b = int(secret_distribution[0][1])
                        h = int(secret_distribution[1])
                        secret_distribution = ((a, b), h)
                    else:
                        a = int(secret_distribution[0])
                        b = int(secret_distribution[1])
                        secret_distribution = (a, b)
            
            ring = False
            if "ring" in params:
                ring = params["ring"]

            if "NTRU" in scheme["scheme"]["assumption"]:
                params = {
                    "n": int(params["n"]),
                    "sd": float(params["sd"]),
                    "q": int(params["q"]),
                    "norm_f": float(params["norm_f"]),
                    "norm_g": float(params["norm_g"]),
                    "claimed": "" if not params["claimed"] else int(params["claimed"]),
                    "category": map(int, params["category"]),
                }
            else:
                # sanitise param object
                k = None if "k" not in params else params["k"]
                params = {
                    "n": int(params["n"]),
                    "sd": float(params["sd"]),
                    "q": int(params["q"]),
                    "claimed": "" if not params["claimed"] else int(params["claimed"]),
                    "category": map(int, params["category"]),
                }
                if k:
                    params["k"] = k

            if secret_distribution:
                params["secret_distribution"] = str(secret_distribution)

            if ring:
                params["ring"] = ring

            # save sanitised param set
            scheme["param"][i] = params
        return scheme

    return json.dumps(map(sanitise_param, estimates_list))

def generate_json(estimates_list):
    """ Generates a JSON string from the estimates and asymptotics list, and add
        it to the website.

    :params estimates_list:         list of estimates generated by estimates.py
    """

    json = "var models = %s;\nvar estimates = %s;"%(
        generate_costs_json(),
        generate_table_json(estimates_list)
    )

    with open(JSONPATH, "w") as f:
        f.write(json)
