﻿using System;
using System.Collections.Generic;

namespace Oni.Dae
{
    internal class Source : Entity
    {
        private float[] floatData;
        private string[] nameData;
        private int stride;
        private int count;

        public Source(IEnumerable<float> data, int stride)
        {
            this.floatData = data.ToArray();
            this.stride = stride;
            this.count = floatData.Length / stride;
        }

        public Source(float[] data, int stride)
        {
            this.floatData = (float[])data.Clone();
            this.stride = stride;
            this.count = data.Length / stride;
        }

        public Source(string[] data, int stride)
        {
            this.nameData = (string[])data.Clone();
            this.stride = stride;
            this.count = data.Length / stride;
        }

        public Source(IList<Vector2> data)
        {
            int count = data.Count;
            float[] array = new float[count * 2];

            for (int i = 0; i < count; i++)
            {
                array[i * 2 + 0] = data[i].X;
                array[i * 2 + 1] = 1.0f - data[i].Y;
            }

            this.floatData = array;
            this.count = count;
            this.stride = 2;
        }

        public Source(IList<Vector3> data)
        {
            int count = data.Count;
            float[] array = new float[count * 3];

            for (int i = 0; i < count; i++)
            {
                array[i * 3 + 0] = data[i].X;
                array[i * 3 + 1] = data[i].Y;
                array[i * 3 + 2] = data[i].Z;
            }

            this.floatData = array;
            this.count = count;
            this.stride = 3;
        }

        public string[] NameData => nameData;
        public float[] FloatData => floatData;
        public int Count => count;

        public int Stride
        {
            get
            {
                return stride;
            }
            set
            {
                stride = value;

                if (floatData != null)
                    count = floatData.Length / stride;
                else
                    count = nameData.Length / stride;
            }
        }

        public static Vector2 ReaderVector2(Source source, int index)
        {
            var data = source.floatData;
            var i = index * source.stride;

            return new Vector2(data[i + 0], data[i + 1]);
        }

        public static Vector2 ReadTexCoord(Source source, int index)
        {
            var data = source.floatData;
            var i = index * source.stride;

            return new Vector2(data[i + 0], 1.0f - data[i + 1]);
        }

        public static Vector3 ReadVector3(Source source, int index)
        {
            var data = source.floatData;
            var i = index * source.stride;

            return new Vector3(data[i + 0], data[i + 1], data[i + 2]);
        }

        public static Vector4 ReadVector4(Source source, int index)
        {
            var data = source.floatData;
            var i = index * source.stride;

            return new Vector4(data[i + 0], data[i + 1], data[i + 2], data[i + 3]);
        }

        public static Imaging.Color ReadColor(Source source, int index)
        {
            return new Imaging.Color(ReadVector4(source, index));
        }
    }
}
