using ActionGame.GameResources.Models;
using ActionGame.RawResources.Manager;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Collections.Generic;
using System.IO;


namespace ActionGame.GameResources.Repository
{
    class FileTileSetRepository : IGameContentRepository<TileSet>
    {
        private IDictionary<Int32, TileSet> ContentByKey { get; set; }
        private IDictionary<Int32, TileSetDefinition> DefinitionsByKey { get; set; }
        private IList<Int32> Keys { get; set; }
        private IRawContentManager rawContentManager;


        public FileTileSetRepository(IRawContentManager rawContentManager, String filename)
        {
            this.rawContentManager = rawContentManager;

            this.ContentByKey = new Dictionary<Int32, TileSet>();
            this.DefinitionsByKey = new Dictionary<Int32, TileSetDefinition>();
            this.Keys = new List<Int32>();

            Load(filename);
        }


        public TileSet GetContent(Int32 key)
        {
            TileSet content = null;

            if (this.ContentByKey.ContainsKey(key))
            {
                content = this.ContentByKey[key];
            }
            else if (this.DefinitionsByKey.ContainsKey(key))
            {
                content = LoadDefinition(this.DefinitionsByKey[key]);
            }

            return content;
        }


        public IList<Int32> GetKeys()
        {
            return this.Keys;
        }


        private void Load(String filename)
        {
            Stream stream = null;
            StreamReader reader = null;
            String line = null;
            String[] lineContents = null;

            stream = File.OpenRead(filename);
            reader = new StreamReader(stream);

            //skip first line
            reader.ReadLine();

            while ((line = reader.ReadLine()) != null)
            {
                lineContents = line.Split(',');

                if (lineContents[0].Equals("") == false)
                {
                    LoadContent(lineContents);
                }
            }

            reader.Close();
        }


        private void LoadContent(String[] lineContents)
        {
            TileSetDefinition definition = new TileSetDefinition();

            definition.Key = Int32.Parse(lineContents[0]);
            definition.TextureKey = Int32.Parse(lineContents[1]);
            definition.X = Int32.Parse(lineContents[2]);
            definition.Y = Int32.Parse(lineContents[3]);
            definition.Width = Int32.Parse(lineContents[4]);
            definition.Height = Int32.Parse(lineContents[5]);
            definition.Passable = Boolean.Parse(lineContents[6]);

            if (lineContents[7].Equals("") == false)
            {
                definition.AnimationSequence = new List<Int32>(Array.ConvertAll(lineContents[7].Split('|'), Int32.Parse));
            }
            else
            {
                definition.AnimationSequence = new List<Int32>();
            }

            this.DefinitionsByKey.Add(definition.Key, definition);
            this.Keys.Add(definition.Key);
        }


        private TileSet LoadDefinition(TileSetDefinition definition)
        {
            TileSet tileSet = null;
            Texture2D rawTexture = this.rawContentManager.TextureRepository.GetContent(definition.TextureKey);

            Texture2D tileTexture = new Texture2D(rawTexture.GraphicsDevice, definition.Width, definition.Height);
            Rectangle tileRect = new Rectangle(definition.X, definition.Y, definition.Width, definition.Height);
            Color[] tileColor = new Color[definition.Width * definition.Height];

            rawTexture.GetData(0, tileRect, tileColor, 0, tileColor.Length);
            tileTexture.SetData(tileColor);

            tileSet = new TileSet(this)
            {
                Key = definition.Key,
                Texture = tileTexture,
                Passable = definition.Passable,
                AnimationSequence = definition.AnimationSequence
            };

            this.ContentByKey.Add(tileSet.Key, tileSet);

            return tileSet;
        }


    }
}
