using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace U.ListOperations
{
    public class IndexClass2D
    {
        private List<int> cardinalities;
        private List<int> multipliers;
        private int n;

        public IndexClass2D(List<int> cardinalities) { this.cardinalities = cardinalities; setMultipliers(); }
        public IndexClass2D(int n1, int n2) { this.cardinalities = new List<int>() { n1, n2 }; setMultipliers(); }
        public IndexClass2D(int n1, int n2, int n3) { this.cardinalities = new List<int>() { n1, n2, n3 }; setMultipliers(); }
        public IndexClass2D(int n1, int n2, int n3, int n4) { this.cardinalities = new List<int>() { n1, n2, n3, n4 }; setMultipliers(); }


        private void setMultipliers()
        {
            if (this.cardinalities == null) { this.n = 0; }
            if (this.cardinalities.Count == 0) { this.n = 0; }
            this.n = 1;
            this.multipliers = UList.sameValues<int>(1, cardinalities.Count);
            for (int i = 0; i < cardinalities.Count; i++)
            {
                this.n = this.n * cardinalities[i];
                for (int j = i + 1; j < cardinalities.Count; j++) { multipliers[i] = multipliers[i] * cardinalities[j]; }
            }
        }

        public List<int> getIndices(int index)
        {
            if (index < 0 || index >= this.n) { return null; }
            List<int> indices = UList.sameValues<int>(0, cardinalities.Count);
            int sum = 0;
            for (int i = 0; i < cardinalities.Count; i++)
            {
                indices[i] = (index - sum) / multipliers[i];
                sum += multipliers[i] * indices[i];
            }
            return indices;
        }
        public int getIndex(List<int> indices)
        {
            for (int i = 0; i < indices.Count; i++) { if (indices[i] < 0 || indices[i] > cardinalities[i]) { return -1; } }
            int index = 0;
            for (int i = 0; i < indices.Count; i++) { index += indices[i] * multipliers[i]; }
            return index;
        }

    }
}
