"""
**tomatojson**: Processing of tomato electrochemistry outputs.
--------------------------------------------------------------

This module parses the electrochemistry ``json`` files generated by tomato.

.. warning::

    This parser is brand-new in `yadg-4.1` and the interface is unstable.

Four sections are expected in each tomato data file:

- ``technique`` section, describing the current technique,
- ``previous`` section, containing status information of the previous file,
- ``current`` section, containing status information of the current file,
- ``data`` section, containing the timesteps.

The reason why both ``previous`` and ``current`` are requires is that the device
status is recorded at the time of data polling, which means the values in ``current``
might be invalid (after the run has finished) or not in sync with the ``data`` (if
a technique change happened). However, ``previous`` may not be present in the first
data file of an experiment.

To determine the measurement errors, the values from BioLogic manual are used: for
measured voltages (:math:`E_{\\text{we}}` and :math:`E_{\\text{ce}}`) this corresponds
to a constant uncertainty of 0.004% of the applied E-range with a maximum of 75 uV, 
while for currents (:math:`I`) this is a constant uncertainty of 0.0015% of the applied
I-range with a maximum of 0.76 uA.

.. codeauthor:: Peter Kraus
"""

import json
import logging

logger = logging.getLogger(__name__)

I_ranges = {
    "1 A": 1e0,
    "100 mA": 1e-1,
    "10 mA": 1e-2,
    "1 mA": 1e-3,
    "100 uA": 1e-4,
    "10 uA": 1e-5,
    "1 uA": 1e-6,
    "100 pA": 1e-7,
}


def process(
    fn: str, encoding: str = "UTF-8", timezone: str = "UTC"
) -> tuple[list, dict, bool]:
    with open(fn, "r") as infile:
        jsdata = json.load(infile)

    technique = jsdata["technique"]
    previous = jsdata.get("previous", None)
    current = jsdata["current"]

    if "uts" in technique:
        uts = technique["uts"]
        fulldate = True
    else:
        uts = 0
        fulldate = False

    if previous is None:
        meta = current
    elif current["status"] == "STOP":
        meta = previous
    elif previous["elapsed_time"] > technique["start_time"]:
        meta = previous
    else:
        meta = current

    I_range = I_ranges[meta["I_range"]]
    E_range = meta["E_range"]["max"] - meta["E_range"]["min"]

    timesteps = []
    for point in jsdata["data"]:
        p = {"fn": fn, "uts": uts + technique["start_time"], "raw": {}}
        for k, v in point.items():
            if k == "time":
                p["uts"] += v
            elif k in {"Ewe", "Ece"}:
                s = max(E_range * 0.0015 / 100, 75e-6)
                p["raw"][k] = {"n": v, "s": s, "u": "V"}
            elif k in {"I"}:
                s = max(I_range * 0.004 / 100, 760e-12)
                p["raw"][k] = {"n": v, "s": s, "u": "A"}
            elif k in {"cycle"}:
                p["raw"]["cycle number"] = v
            else:
                logger.cricital(f"parameter {k}: {v} not understood.")
        p["raw"]["loop number"] = technique["loop_number"]
        p["raw"]["technique"] = technique["name"]
        p["raw"]["index"] = technique["index"]
        timesteps.append(p)

    return timesteps, None, fulldate
