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

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace MojaPierwszaGraMonoGame
{
    class SferaZBuforemIndeksow
    {
        private GraphicsDevice gd;
        private VertexBuffer buforWerteksów = null;
        private IndexBuffer buforIndeksów = null;

        private float promień;
        private int liczbaSekcjiNaRównoleżnikach, liczbaSekcjiNaPołudnikach;

        public SferaZBuforemIndeksow(
            GraphicsDevice gd,
            float promień,
            int liczbeSekcjiNaRównoleżnikach,
            int liczbaSekcjiNaPołudnikach,
            Color kolor)
        {
            this.gd = gd;
            this.promień = promień;
            this.liczbaSekcjiNaRównoleżnikach = liczbeSekcjiNaRównoleżnikach;
            this.liczbaSekcjiNaPołudnikach = liczbaSekcjiNaPołudnikach;

            int całkowitaLiczbaWerteksów = (liczbeSekcjiNaRównoleżnikach + 1) * (liczbaSekcjiNaPołudnikach + 1);
            List<VertexPositionColor> listaWerteksów = new List<VertexPositionColor>(całkowitaLiczbaWerteksów);
            double przyrostKątaTheta = Math.PI / liczbaSekcjiNaPołudnikach;
            double przyrostKątaPhi = 2 * Math.PI / liczbeSekcjiNaRównoleżnikach;

            for (int i = 0; i <= liczbaSekcjiNaPołudnikach; i++)
            {
                double kątTheta = i * przyrostKątaTheta;
                float _wysokość = (float)(promień * Math.Cos(kątTheta));
                float _promień = (float)(promień * Math.Sin(kątTheta));

                for (int j = 0; j <= liczbeSekcjiNaRównoleżnikach; j++)
                {
                    double kątPhi = j * przyrostKątaPhi;
                    int indeks = j + i * (liczbeSekcjiNaRównoleżnikach + 1);

                    Vector3 położenie = new Vector3(_promień * (float)Math.Cos(kątPhi), -_promień * (float)Math.Sin(kątPhi), _wysokość);

                    listaWerteksów.Add(new VertexPositionColor(położenie, kolor));
                }
            }
            ZbudujBuforWerteksów(listaWerteksów.ToArray());

            int liczbaIndeksówWPaśmie = 2 * (liczbaSekcjiNaPołudnikach + 1);
            int całkowitaLiczbaIndeksów = liczbaIndeksówWPaśmie * liczbaSekcjiNaPołudnikach;
            List<int> listaIndeksów = new List<int>(całkowitaLiczbaIndeksów);
            for (int i = 0; i < całkowitaLiczbaIndeksów / 2; i++)
            {
                listaIndeksów.Add(i);
                listaIndeksów.Add(i + (liczbeSekcjiNaRównoleżnikach + 1));
            }
            ZbudujBuforIndeksów(listaIndeksów.ToArray());
        }

        private void ZbudujBuforWerteksów(VertexPositionColor[] tablicaWerteksów)
        {
            buforWerteksów = new VertexBuffer(gd, VertexPositionColor.VertexDeclaration, tablicaWerteksów.Length, BufferUsage.WriteOnly);
            buforWerteksów.SetData<VertexPositionColor>(tablicaWerteksów);
        }

        private void ZbudujBuforIndeksów(int[] tablicaIndeksów)
        {
            buforIndeksów = new IndexBuffer(gd, IndexElementSize.ThirtyTwoBits, tablicaIndeksów.Length, BufferUsage.WriteOnly);
            buforIndeksów.SetData<int>(tablicaIndeksów);
        }

        public void Rysuj(Effect efekt)
        {
            int liczbaWerteksówWPaśmie = (liczbaSekcjiNaRównoleżnikach + 1) * 2;

            foreach (EffectPass przebieg in efekt.CurrentTechnique.Passes)
            {
                przebieg.Apply();
                gd.Indices = buforIndeksów;
                gd.SetVertexBuffer(buforWerteksów);
                for (int i = 0; i < liczbaSekcjiNaPołudnikach; i++)
                {
                    gd.DrawIndexedPrimitives(PrimitiveType.TriangleStrip, 0, 0, liczbaWerteksówWPaśmie, i * liczbaWerteksówWPaśmie, liczbaSekcjiNaRównoleżnikach * 2);
                }
            }
        }
    }
}
