using DotNext;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace BsdlParser;

/// <summary>
/// [TODO:description]
/// </summary>
public class BoundaryScanRegs
{
    /// <summary>
    /// [TODO:description]
    /// </summary>
    public class CellEntry
    {
        /// <summary>
        /// [TODO:description]
        /// </summary>
        [JsonProperty("cell_number")]
        [JsonRequired]
        public int CellNumber { get; set; }

        /// <summary>
        /// [TODO:description]
        /// </summary>
        [JsonProperty("cell_name")]
        [JsonRequired]
        public string CellName { get; set; } = "UnknownCellName";

        /// <summary>
        /// [TODO:description]
        /// </summary>
        [JsonProperty("port_id")]
        public string? PortID { get; set; }

        /// <summary>
        /// [TODO:description]
        /// </summary>
        [JsonProperty("function")]
        [JsonRequired]
        public string? Function { get; set; }

        /// <summary>
        /// [TODO:description]
        /// </summary>
        [JsonProperty("safe_bit")]
        [JsonRequired]
        public string? SafeBit { get; set; }

        /// <summary>
        /// [TODO:description]
        /// </summary>
        [JsonProperty("ccell")]
        public string? CCell { get; set; }

        /// <summary>
        /// [TODO:description]
        /// </summary>
        [JsonProperty("disabel_value")]
        public string? DisableValue { get; set; }

        /// <summary>
        /// [TODO:description]
        /// </summary>
        [JsonProperty("disabel_result")]
        public string? DisableResult { get; set; }
    }

    /// <summary>
    /// [TODO:description]
    /// </summary>
    [JsonProperty("register_length")]
    [JsonRequired]
    public int RegisterLength { get; set; }

    /// <summary>
    /// [TODO:description]
    /// </summary>
    [JsonProperty("registers")]
    [JsonRequired]
    public CellEntry[] Registers { get; set; } = new CellEntry[] { };

}

/// <summary>
/// [TODO:description]
/// </summary>
public class Parser
{
    private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();

    private const string BOUNDARY_REGS_DESP = "boundary_registers.json";

    /// <summary>
    /// [TODO:description]
    /// </summary>
    public JObject BoundaryRegsDesp { get; }

    /// <summary>
    /// [TODO:description]
    /// </summary>
    /// <returns>[TODO:return]</returns>
    public Parser()
    {
        var filePath = Path.Combine(Environment.CurrentDirectory, BOUNDARY_REGS_DESP);
        if (!Path.Exists(filePath))
            throw new Exception($"Counld not find boundary_registers.json in {filePath}");

        this.BoundaryRegsDesp = JObject.Parse(File.ReadAllText(filePath));
    }

    /// <summary>
    /// [TODO:description]
    /// </summary>
    public Optional<int> GetBoundaryRegsNum()
    {
        var ret = this.BoundaryRegsDesp["register_length"];
        if (ret is null) return new();
        return Convert.ToInt32(ret);
    }

    /// <summary>
    /// [TODO:description]
    /// </summary>
    /// <returns>[TODO:return]</returns>
    public Optional<List<BoundaryScanRegs.CellEntry>> GetBoundaryPorts()
    {
        var registers = this.BoundaryRegsDesp["registers"]?.ToList();
        if (registers is null) return new();

        var cellList = new List<BoundaryScanRegs.CellEntry>();
        foreach (var item in registers)
        {
            var cell = item.ToObject<BoundaryScanRegs.CellEntry>();
            if (cell is null) return new();
            cellList.Add(cell);
        }

        return cellList;
    }

    /// <summary>
    /// [TODO:description]
    /// </summary>
    /// <returns>[TODO:return]</returns>
    public Optional<List<BoundaryScanRegs.CellEntry>> GetBoundaryLogicalPorts()
    {
        var registers = this.BoundaryRegsDesp["registers"]?.ToList().Where((item) =>
        {
            return item["port_id"] is not null;
        });
        if (registers is null) return new();

        var cellList = new List<BoundaryScanRegs.CellEntry>();
        foreach (var item in registers)
        {
            var cell = item.ToObject<BoundaryScanRegs.CellEntry>();
            if (cell is null) return new();
            cellList.Add(cell);
        }

        return cellList;
    }

    // public Result<string> GetLogicalPorts()
    // {
    //     using (Py.GIL())
    //     {
    //         using (PyModule scope = Py.CreateScope())
    //         {
    //             string code = $@"
    //                 bsdl_parser = BsdlParser({this.filePath})
    //                 result = json.dumps(bsdl_parser.GetLogicPortDesp(), indent=2)
    //             ";
    //
    //             var localVariables = new PyDict();
    //             scope.Exec(code, localVariables);
    //             if (!localVariables.HasKey("result"))
    //                 return new(new Exception($"PythonNet doesn't has result from dict: {localVariables}"));
    //
    //             var result = localVariables.GetItem("result");
    //             if (result is null)
    //                 return new(new Exception($"PythonNet get null from dict: {localVariables}"));
    //
    //             var resultString = result.ToString();
    //             if (resultString is null)
    //                 return new(new Exception($"Pythonnet convert PyObject to string failed :{result}"));
    //             return resultString;
    //         }
    //     }
    // }
}
