namespace Jayrock.Json.Conversion.Converters
{
    #region Imports
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.IO;
    using Jayrock.Json.Conversion;
    #endregion

    internal sealed class GenericListImporter : ImporterBase
    {
        public GenericListImporter(Type listType) : base(AssertArrayType(listType)) { }

        private static Type AssertArrayType(Type type)
        {
            if (type == null)
                throw new ArgumentException(string.Format("{0} is null.", type.FullName), "listType");

            if (!type.IsGenericType || type.GetGenericTypeDefinition() != typeof(List<>))
                throw new ArgumentException(string.Format("{0} is not a List<>.", type.FullName), "listType");

            return type;
        }

        protected override object ImportFromArray(ImportContext context, JsonReader reader)
        {
            Debug.Assert(context != null);
            Debug.Assert(reader != null);

            reader.Read();

            IList list = Activator.CreateInstance(OutputType) as IList;
            Type elementType = OutputType.GetGenericArguments()[0];

            while (reader.TokenClass != JsonTokenClass.EndArray)
                list.Add(context.Import(elementType, reader));

            return ReadReturning(reader, list);
        }

        protected override object ImportFromBoolean(ImportContext context, JsonReader reader)
        {
            return ImportScalarAsArray(context, reader);
        }

        protected override object ImportFromNumber(ImportContext context, JsonReader reader)
        {
            return ImportScalarAsArray(context, reader);
        }

        protected override object ImportFromString(ImportContext context, JsonReader reader)
        {
            string readstr = reader.Text.Trim();
            if (readstr.Length >= 2 && readstr.StartsWith("[") && readstr.EndsWith("]"))
            {
                return ReadReturning(reader, Import(context, new JsonTextReader(new StringReader(readstr))));
            }
            else
            {
                return ImportScalarAsArray(context, reader);
            }
        }

        private object ImportScalarAsArray(ImportContext context, JsonReader reader)
        {
            Debug.Assert(context != null);
            Debug.Assert(reader != null);

            Type elementType = OutputType.GetGenericArguments()[0];
            IList list = Activator.CreateInstance(OutputType) as IList;
            list.Add(context.Import(elementType, reader));
            return list;
        }
    }
}
