using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json.Linq;

namespace EDPlayerJournal;

public class FactionState {
    public string? State { get; set; }
    public long? Trend { get; set; }

    public static FactionState? FromJSON(JObject j) {
        if (j == null) {
            return null;
        }

        FactionState s = new FactionState() {
            State = j.Value<string>("State"),
            Trend = j.Value<long?>("Trend"),
        };

        if (string.IsNullOrEmpty(s.State)) {
            return null;
        }

        return s;
    }
}

public class Factions {
    /// <summary>
    /// Internal name for the Pilots Federation faction
    /// </summary>
    public static string PilotsFederationInternal = "$faction_PilotsFederation;";

    /// <summary>
    /// Name used for Pilots Federation in vouchers
    /// </summary>
    public static string PilotsFederationVouchers = "PilotsFederation";

    /// <summary>
    /// Friendly name of the Pilots Federation
    /// </summary>
    public static string PilotsFederation = "Pilots' Federation";

    /// <summary>
    /// Internal name for the Thargoid faction
    /// </summary>
    public static string ThargoidInternal = "$faction_Thargoid;";

    /// <summary>
    /// Localised name of the Thargoids
    /// </summary>
    public static string Thargoid = "Thargoids";

    /// <summary>
    /// The faction the fleet carriers use.
    /// </summary>
    public static string FleetCarrier = "FleetCarrier";

    public static bool IsPilotsFederation(string? name) {
        if (name == null) {
            return false;
        }

        if (string.Compare(name, PilotsFederationInternal) == 0 ||
            string.Compare(name, PilotsFederationVouchers) == 0 ||
            string.Compare(name, PilotsFederation) == 0) {
            return true;
        }

        return false;
    }

    public static bool IsThargoid(string? name) {
        if (name == null) {
            return false;
        }

        if (string.Compare(name, ThargoidInternal) == 0 ||
            string.Compare(name, Thargoid) == 0) {
            return true;
        }

        return false;
    }

    /// <summary>
    /// Compares two factions names and sees if they are the same faction. Since
    /// factions can have an internal name, and a public name, this function takes
    /// these into account.
    /// </summary>
    /// <param name="a"></param>
    /// <param name="b"></param>
    /// <returns></returns>
    public static int CompareFactions(string? a, string? b) {
        if (a == null || b == null) {
            return -1;
        }

        if (IsPilotsFederation(a) && IsPilotsFederation(b)) {
            return 0;
        }

        if (IsThargoid(a) && IsThargoid(b)) {
            return 0;
        }

        return string.Compare(a, b);
    }
}

public class Faction {
    public string? Name { get; set; }
    public string? FactionState { get; set; }
    public string? Government { get; set; }
    public double Influence { get; set; }
    public string? Allegiance { get; set; }
    public string? Happiness { get; set; }
    public string? HappinessLocalised { get; set; }
    public double MyReputation { get; set; }
    public bool SquadronFaction { get; set; } = false;
    public bool HomeSystem { get; set; } = false;

    public List<FactionState> RecoveringStates { get; set; } = new List<FactionState>();
    public List<FactionState> ActiveStates { get; set; } = new List<FactionState>();
    public List<FactionState> PendingStates { get; set; } = new List<FactionState>();

    public static Faction? FromJSON(JObject j) {
        if (j == null) {
            return null;
        }

        Faction f = new Faction() {
            Name = j.Value<string>("Name") ?? "",
            FactionState = j.Value<string>("FactionState") ?? "",
            Government = j.Value<string>("Government") ?? "",
            Influence = j.Value<double?>("Influence") ?? 1.0,
            Allegiance = j.Value<string>("Allegiance") ?? "",
            Happiness = j.Value<string>("Happiness") ?? "",
            HappinessLocalised = j.Value<string>("Happiness_Localised") ?? "",
            MyReputation = j.Value<double?>("MyReputation") ?? 1.0,
            SquadronFaction = (j.Value<bool?>("SquadronFaction") ?? false),
            HomeSystem = (j.Value<bool?>("HomeSystem") ?? false),
        };

        if (string.IsNullOrEmpty(f.Name)) {
            return null;
        }

        JArray? recovering_states = j.Value<JArray>("RecoveringStates");
        if (recovering_states != null) {
            foreach (JObject s in recovering_states) {
                FactionState? state = EDPlayerJournal.FactionState.FromJSON(s);
                if (state != null) {
                    f.RecoveringStates.Add(state);
                }
            }
        }

        JArray? active_states = j.Value<JArray>("ActiveStates");
        if (active_states != null) {
            foreach (JObject s in active_states) {
                FactionState? state = EDPlayerJournal.FactionState.FromJSON(s);
                if (state != null) {
                    f.ActiveStates.Add(state);
                }
            }
        }

        JArray? pending_states = j.Value<JArray>("PendingStates");
        if (pending_states != null) {
            foreach (JObject s in pending_states) {
                FactionState? state = EDPlayerJournal.FactionState.FromJSON(s);
                if (state != null) {
                    f.PendingStates.Add(state);
                }
            }
        }

        return f;
    }
}
