// Keeps track of all construction materials (ingots and ores) on the grid
// TODO: also track unprocessed stuff?
using System;
using System.Collections.Generic;
using System.Text;
using Sandbox.ModAPI.Ingame;
using VRage.Game.GUI.TextPanel;
using VRage.Game.ModAPI.Ingame;

namespace IngameScript
{
    partial class Program
    {
        [Flags]
        public enum ResourceType
        {
            Ore = 0x1,
            Ingot = 0x2,
            Component = 0x4,
        }

        public class Resource
        {
            public string Name { get; private set; }
            public string DisplayName { get; private set; }
            public ResourceType Type { get; private set; }
            public float OreAmount { get; set; } = 0f;
            public float IngotAmount { get; set; } = 0f;
            public float ComponentAmount { get; set; } = 0f;

            public MyItemType OreType { get; private set; }
            public MyItemType IngotType { get; private set; }
            public MyItemType ComponentType { get; private set; }

            private StringBuilder _builder = new StringBuilder();

            public Resource(string name, string displayName = "", ResourceType type = ResourceType.Ore | ResourceType.Ingot)
            {
                Name = name;
                DisplayName = displayName == "" ? name : displayName;
                Type = type;
                if (Type.HasFlag(ResourceType.Ore)) OreType = MyItemType.MakeOre(Name);
                if (Type.HasFlag(ResourceType.Ingot)) IngotType = MyItemType.MakeIngot(Name);
                if (Type.HasFlag(ResourceType.Ingot)) ComponentType = MyItemType.MakeComponent(Name);
            }

            public void Reset()
            {
                OreAmount = 0f;
                IngotAmount = 0f;
                ComponentAmount = 0f;
            }

            public override string ToString()
            {
                _builder.Clear();
                _builder.Append(DisplayName);
                _builder.Append(": ");
                if (Type.HasFlag(ResourceType.Ore))
                {
                    _builder.Append(OreAmount.ToString("N0"));
                    _builder.Append(' ');
                }
                if (Type.HasFlag(ResourceType.Ingot))
                {
                    _builder.Append(IngotAmount.ToString("N0"));
                    _builder.Append(' ');
                }
                if (Type.HasFlag(ResourceType.Component))
                {
                    _builder.Append(ComponentAmount.ToString("N0"));
                    _builder.Append(' ');
                }
                return _builder.ToString();
            }
        }

        // TODO: factor out the display code once it is more complex
        public class ResourceReport
        {
            private Program _program;
            private IConsole _console;
            private IMyTextSurface _display;
            private StringBuilder _builder = new StringBuilder();
            private List<IMyInventory> _inventories = new List<IMyInventory>();

            // TODO: make tracked resources configurable, and make it configurable/displayable from multiple screens...
            // (and probably add support for *components* as well, oy)
            private Dictionary<string, Resource> _resources = new Dictionary<string, Resource>
            {
                ["Iron"] = new Resource("Iron"),
                ["Silicon"] = new Resource("Silicon"),
                ["Nickel"] = new Resource("Nickel"),
                ["Cobalt"] = new Resource("Cobalt"),
                ["Gold"] = new Resource("Gold"),
                ["Silver"] = new Resource("Silver"),
                ["Platinum"] = new Resource("Platinum"),
                ["Magnesium"] = new Resource("Magnesium"),
                ["Uranium"] = new Resource("Uranium"),
                ["Stone"] = new Resource("Stone", "", ResourceType.Ore),
                ["Ice"] = new Resource("Ice", "", ResourceType.Ore),
                ["Gravel"] = new Resource("Gravel", "", ResourceType.Ingot),
                ["Scrap"] = new Resource("Scrap"),
                ["Prototech"] = new Resource("PrototechScrap", "Prototech Scrap", ResourceType.Ingot),
            };

            public ResourceReport(IMyTextSurface display, Program program)
            {
                _program = program;
                _display = display;
                _console = new PrefixedConsole(_program.Console, "OreReport");

                // Configure display
                _display.ContentType = ContentType.TEXT_AND_IMAGE;
                _display.WriteText("Initializing...");

                // find all the inventories
                List<IMyTerminalBlock> invBlocks = new List<IMyTerminalBlock>();
                program.GridTerminalSystem.GetBlocksOfType(invBlocks, blockFilter);
                foreach (IMyTerminalBlock block in invBlocks)
                {
                    IMyInventory inv = block.GetInventory();
                    _inventories.Add(inv);
                }

                _console.Print($"Scanning {_inventories.Count} inventories.");
            }

            public void Update()
            {
                foreach (Resource res in _resources.Values) res.Reset();
                foreach (IMyInventory inv in _inventories)
                {
                    foreach (Resource res in _resources.Values)
                    {
                        res.OreAmount += (float)inv.GetItemAmount(res.OreType);
                        res.IngotAmount += (float)inv.GetItemAmount(res.IngotType);
                    }
                }
            }

            // TODO: just text for now; turn this into a nice graphical display eventually
            public void Draw()
            {
                _builder.Clear();
                _builder.AppendLine("RESOURCE REPORT");
                _builder.AppendLine();
                foreach (Resource res in _resources.Values)
                {
                    _builder.AppendLine(res.ToString());
                }
                _display.WriteText(_builder.ToString());
            }

            private bool blockFilter(IMyTerminalBlock block)
            {
                return block.IsSameConstructAs(_program.Me) && block.InventoryCount > 0;
            }
        }
    }
}