using System;
using System.Collections.Generic;
using Server;
using Server.Engines.Craft;
using Server.Items;

namespace Server.Engines.Craft
{
    public class CraftQueueEntry
    {
        public CraftSystem System { get; set; }
        public CraftItem Item { get; set; }
        public BaseTool Tool { get; set; }
        public int Amount { get; set; }
        public int Made { get; set; }
        public int Failed { get; set; }
        public int Exceptional { get; set; }

        public CraftQueueEntry( CraftSystem system, CraftItem item, BaseTool tool )
        {
            System = system;
            Item = item;
            Tool = tool;
            Amount = 1; 
            Made = 0;
            Failed = 0;
            Exceptional = 0;
        }
    }

    public class CraftQueue
    {
        private static Dictionary<Mobile, CraftQueue> m_Queues = new Dictionary<Mobile, CraftQueue>();

        public List<CraftQueueEntry> Entries { get; set; }
        public bool IsPaused { get; set; }

        public CraftQueue()
        {
            Entries = new List<CraftQueueEntry>();
            IsPaused = true; // Now defaults to Paused so the first click says "START"
        }

        public static CraftQueue GetQueue( Mobile m )
        {
            if ( !m_Queues.ContainsKey( m ) )
                m_Queues[m] = new CraftQueue();

            return m_Queues[m];
        }

        public static void AddEntry( Mobile m, CraftSystem system, CraftItem item, BaseTool tool )
        {
            CraftQueue queue = GetQueue( m );
            queue.Entries.Add( new CraftQueueEntry( system, item, tool ) );
        }

        public static void Pause( Mobile m, string reason )
        {
            CraftQueue queue = GetQueue( m );
            if ( !queue.IsPaused )
            {
                queue.IsPaused = true;
                m.SendMessage( 0x20, $"Crafting queue paused: {reason}" );
            }
        }

        public static void HandleResult( Mobile from, bool success, bool exceptional )
        {
            CraftQueue queue = GetQueue( from );
            
            if ( queue.IsPaused || queue.Entries.Count == 0 ) 
                return;

            // Find the first item that still needs crafting
            CraftQueueEntry entry = null;
            foreach ( var e in queue.Entries )
            {
                if ( e.Amount > 0 )
                {
                    entry = e;
                    break;
                }
            }

            if ( entry == null ) return;

            // Tally the stats
            if ( success )
            {
                entry.Made++;
                if ( exceptional ) 
                    entry.Exceptional++;
            }
            else
            {
                entry.Failed++;
            }

            // Decrement the remaining amount
            entry.Amount--;

            // Fire the next craft automatically! 
            Timer.DelayCall( TimeSpan.FromSeconds( 1.5 ), new TimerStateCallback( ProcessQueue ), from );
        }

        public static void ProcessQueue( object state )
        {
            Mobile from = (Mobile)state;
            CraftQueue queue = GetQueue( from );

            if ( queue.IsPaused ) 
                return;

            // Find the active item
            CraftQueueEntry entry = null;
            foreach ( var e in queue.Entries )
            {
                if ( e.Amount > 0 )
                {
                    entry = e;
                    break;
                }
            }

            if ( entry == null )
            {
                from.SendMessage( 0x480, "Your crafting queue is complete!" );
                queue.IsPaused = true; // Auto-pause for the next time they use it
                return;
            }

            // Safety Check: Did the tool break?
            if ( entry.Tool == null || entry.Tool.Deleted || entry.Tool.UsesRemaining <= 0 )
            {
                Type toolType = entry.Tool != null ? entry.Tool.GetType() : null;
                BaseTool newTool = null;

                // Search the player's backpack for a valid replacement tool
                if ( toolType != null && from.Backpack != null )
                {
                    Item[] tools = from.Backpack.FindItemsByType( toolType );
                    foreach ( Item t in tools )
                    {
                        BaseTool bt = t as BaseTool;
                        if ( bt != null && !bt.Deleted && bt.UsesRemaining > 0 )
                        {
                            newTool = bt;
                            break; // Found a valid spare!
                        }
                    }
                }

                if ( newTool != null )
                {
                    // Swap the broken tool out for the spare and keep going!
                    entry.Tool = newTool;
                    from.SendMessage( 0x480, "A broken tool was replaced with a spare from your backpack." );
                }
                else
                {
                    // No spares found. Pause so they can go get one.
                    Pause( from, "Tool broken. Please place a new one in your backpack and hit Start." );
                    return;
                }
            }

            // Figure out what resource (wood, ingot type, etc) they had selected
            CraftContext context = entry.System.GetContext( from );
            Type typeRes = null;
            if ( context != null )
            {
                CraftSubResCol res = entry.System.CraftSubRes;
                int resIndex = context.LastResourceIndex;
                if ( resIndex > -1 && resIndex < res.Count )
                    typeRes = res.GetAt( resIndex ).ItemType;
            }

            // Close existing gumps so the screen doesn't spam
            from.CloseGump( typeof( CraftGump ) );
            from.CloseGump( typeof( CraftQueueGump ) );
            from.CloseGump( typeof( CraftGumpItem ) );

            // Start the next craft!
            entry.Item.Craft( from, entry.System, typeRes, entry.Tool );
        }
    }
}
