import json
import requests
import traceback

from .__init__ import server


class Configuration():
    def __init__(self, config_json):

        """
        Creates a new Configuration object given the raw JSON
        returned by the server by next_configuration in the
        Experiment class.

        Args:
            config_json (JSON/dict): raw configuration JSON returned by the server

        """

        self.data = config_json

    def __getitem__(self, key):

        """
        Allows for dict-like retrieval of elements.

        Args:
            key (str): Name of a hyperparameter in the config

        Returns:
            value: Int, float, or enum associated with hyperparameter
        """

        value = self.data["config"][key]
        if value is None:
            print ("The key '%s' does not exist in this configuration")
        else:
            return self.data["config"][key]

    def get_eval_id(self):

        """
        Retrieves the ID corresponding to the evaluation in the database

        Returns:
            str: Evaluation ID

        """

        return self.data["eval_id"]

    def get_value(self, key):

        """
        Retrieves the value associated with a given variable.

        Args:
            name (str): Name of the variable to retrieve

        Returns:
            str: Value of the variable with key 'name'

        """

        value = self.data["config"][key]
        if value is None:
            print ("The key '%s' does not exist in this configuration")
        else:
            return self.data["config"][key]

    def report_loss(self, loss):

        """
        Adds a loss value to this configuration and returns it to the server.

        Args:
            loss (float): Loss generated by running a model with this configuration

        Todo: There should be something returned from the post request indicate success/failure
        """

        try:
            loss = float(loss)
            self.data["result"] = loss
            r = requests.post(server + "report", json=self.data)
        except ValueError:
            traceback.print_stack()
            print("Error: reported loss must be a parsable float")

