using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using DataClient.Struct;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using NLog;

namespace DataClient
{
	public static class Configuration
	{
    private static Logger log = LogManager.GetCurrentClassLogger();
    public static Dictionary<int,ConfAnalog[]> InitAnalogList(string confDir, int[] listVdp)
		{
			var res = new Dictionary<int, ConfAnalog[]>();
      string jsonString;
      var confFile = Path.Combine(confDir, "default.json");
      try { jsonString = File.ReadAllText(confFile); }
      catch (Exception e) { log.Error(e, "Can't read config file from " + confDir + "."); throw; }
      var subres = InitAnalogVdp(confDir);
      foreach(var vdp in listVdp)
			{
        if (res.ContainsKey(vdp)) continue;
        var tmp = InitAnalogVdp(confDir, vdp, subres);
        res.Add(vdp, tmp);
			}
      return res;
		}
    public static ConfAnalog[] InitAnalogVdp(string confDir, int vdp = -1, ConfAnalog[] analogs = null)
    {
      if (analogs == null) analogs = Array.Empty<ConfAnalog>();
      var res = new List<ConfAnalog>(analogs);
      var searchPattern = vdp == -1 ? "*default.json" : "*" + vdp.ToString() + "*.json";
      var files = Directory.GetFiles(confDir, searchPattern);
      foreach (var file in files)
      {
        //check file
        if (vdp != -1)
          if (!int.TryParse(Path.GetFileNameWithoutExtension(file), out int fVdp) || fVdp != vdp)
            continue;
        //check JSON
        string jsonString;
        try { jsonString = File.ReadAllText(file); }
        catch (Exception e) { log.Warn(e, "Can't read config file from " + confDir + "."); continue; }
        //try json
        var conf = (JObject)JsonConvert.DeserializeObject(jsonString);
        if (!conf.HasValues) { continue; };
        //check deleteAll
        if (conf["deleteAll"].Type == JTokenType.Boolean && (bool)conf["deleteAll"])
          res.Clear();
        //check deleteIdAnalog
        if (conf["delete"].Type == JTokenType.Array)
          foreach (var idAnalog in conf["delete"])
            if (idAnalog.Type == JTokenType.Integer)
              res.RemoveAll(x => x.id == (int)idAnalog);
        //check add
        if (conf["add"].Type == JTokenType.Array)
          foreach (var a in conf["add"])
          {
            var ca = new ConfAnalog();
            if (a["id"].Type != JTokenType.Integer || (int)a["id"] < 0) continue;
            else ca.id = (int)a["id"];
            if (a["name"].Type == JTokenType.String) ca.name = (string)a["name"];
            if (a["sname"].Type == JTokenType.String) ca.sname = (string)a["sname"];
            else ca.sname = ca.name;
            if (a["measure"].Type == JTokenType.String) ca.measure = (string)a["measure"];
            if (a["mul"].Type == JTokenType.Integer || a["mul"].Type == JTokenType.Float) ca.mul = (float)a["mul"];
            if (a["min"].Type == JTokenType.Integer || a["min"].Type == JTokenType.Float) ca.min = (float)a["min"];
            if (a["max"].Type == JTokenType.Integer || a["max"].Type == JTokenType.Float) ca.max = (float)a["max"];
            if (a["zero"].Type == JTokenType.Integer || a["zero"].Type == JTokenType.Float) ca.zero = (float)a["zero"];
            if (a["logarithm"].Type == JTokenType.Boolean) ca.logarithm = (bool)a["logarithm"];
            var bi = new List<int>();
            if (a["byteId"].Type == JTokenType.Array)
              foreach (var b in a["byteId"])
                if (b.Type == JTokenType.Integer)
                  bi.Add((int)b);
            ca.byteId = bi.ToArray();
            res.RemoveAll(x => x.id == ca.id);
            res.Add(ca);
          }
      }
      return res.ToArray();
    }
	}
}
