using Android.Content;
using Android.Graphics;
using Android.Util;
using Android.Views;
using System.Collections.Generic;

namespace Grafika2D
{
    public class Grafika2DView : View
    {
        private Paint paint;
        int szerokość, wysokość;

        private Rect prost1, prost2, prost3;
        private Path ścieżka;
        private Bitmap obraz;

        private long aktualnyCzas = -1, poprzedniCzas = -1;

        public Grafika2DView(Context context, IAttributeSet attributeSet)
            : base(context, attributeSet)
        {
            paint = new Paint(PaintFlags.AntiAlias);
            paint.SetStyle(Paint.Style.FillAndStroke);
            paint.StrokeWidth = 3;

            szerokość = this.Width;
            wysokość = this.Height;
            Log.Debug("View.ctor", "Szerokość: " + szerokość.ToString());
            Log.Debug("View.ctor", "Wysokość: " + wysokość.ToString());

            SetBackgroundColor(Color.Cyan);
        }

        protected override void OnSizeChanged(int w, int h, int oldw, int oldh)
        {
            base.OnSizeChanged(w, h, oldw, oldh);

            szerokość = Width;
            wysokość = Height;
            Log.Debug("View.onSizeChanged", "Szerokość: " + szerokość.ToString());
            Log.Debug("View.onSizeChanged", "Wysokość: " + wysokość.ToString());

            //obiekty wykorzystywane w OnDraw
            prost1 = new Rect(0, wysokość / 2, szerokość, wysokość);
            prost2 = new Rect(szerokość / 10, wysokość / 3, 5 * szerokość / 10, 2 * wysokość / 3);
            prost3 = new Rect(7 * szerokość / 40, 9 * wysokość / 20, 5 * szerokość / 20, 2 * wysokość / 3);

            ścieżka = new Path();
            ścieżka.SetFillType(Path.FillType.EvenOdd);
            ścieżka.MoveTo(szerokość / 10, wysokość / 3);
            ścieżka.LineTo(2 * szerokość / 10, wysokość / 6);
            ścieżka.LineTo(4 * szerokość / 10, wysokość / 6);
            ścieżka.LineTo(5 * szerokość / 10, wysokość / 3);
            ścieżka.LineTo(szerokość / 10, wysokość / 3);
            ścieżka.Close();

            obraz = BitmapFactory.DecodeResource(Resources, Resource.Mipmap.ic_launcher);
            if (obraz == null) Log.Error("View.ctor", "Obraz nie został poprawnie wczytany");
        }

        protected override void OnDraw(Canvas canvas)
        {
            base.OnDraw(canvas);

            paint.SetStyle(Paint.Style.FillAndStroke);
            paint.StrokeWidth = 3;

            //słońce
            paint.Color = Color.Yellow;
            {
                int x0 = 4 * szerokość / 5;
                int y0 = wysokość / 4;
                int r1 = wysokość / 10;
                int r2 = 2 * r1;
                canvas.DrawCircle(x0, y0, r1, paint);

                int ilePromieni = 8;
                double wsp = 2 * Java.Lang.Math.Pi / ilePromieni;
                for (int i = 0; i < ilePromieni; ++i)
                {
                    canvas.DrawLine(x0, y0, x0 + r2 * (float)Java.Lang.Math.Cos(wsp * i), y0 + r2 * (float)Java.Lang.Math.Sin(wsp * i), paint);
                }
            }

            //ziemia
            paint.Color = Color.Argb(255, 191, 255, 0);
            canvas.DrawRect(prost1, paint);

            //ściany
            paint.Color = Color.White;
            canvas.DrawRect(prost2, paint);

            //drzwi
            paint.Color = Color.Argb(255, 0, 125, 0);
            canvas.DrawRect(prost3, paint);

            //okno
            paint.Color = Color.Cyan;
            for (int ix = 0; ix < 2; ++ix)
            {
                for (int iy = 0; iy < 2; ++iy)
                {
                    int x0 = 13 * szerokość / 40;
                    int y0 = 2 * wysokość / 5;
                    int x1 = x0 + ix * szerokość / 15;
                    int y1 = y0 + iy * wysokość / 15;
                    int x2 = x1 + szerokość / 20;
                    int y2 = y1 + wysokość / 20;
                    canvas.DrawRect(new Rect(x1, y1, x2, y2), paint);
                }
            }

            //dach
            paint.Color = Color.Red;
            canvas.DrawPath(ścieżka, paint);

            /*
            //android	
            {
                int x0 = szerokość / 2;
                int y0 = 4 * wysokość / 10;
                float wsp = (float)obraz.Height / obraz.Width;
                int dx = szerokość / 5;
                int dy = (int)(y0 * wsp);
                canvas.DrawBitmap(obraz, null, new Rect(x0, y0, x0 + dx, y0 + dy), paint);
            }
            */

            //czas do animacji
            if (aktualnyCzas < 0)
            {
                aktualnyCzas = Java.Lang.JavaSystem.CurrentTimeMillis();
                poprzedniCzas = aktualnyCzas;
            }
            else
            {
                poprzedniCzas = aktualnyCzas;
                aktualnyCzas = Java.Lang.JavaSystem.CurrentTimeMillis();
            }

            const double f = 0.001;

            //android - animacja		
            {
                int x0 = szerokość / 2;
                int y0 = 4 * wysokość / 10;
                float wsp = (float)obraz.Height / obraz.Width;
                int dx = szerokość / 5;
                int dy = (int)(y0 * wsp);
                int xs = (int)(szerokość / 4 * Java.Lang.Math.Sin(f * aktualnyCzas)); //dodane!!!
                canvas.DrawBitmap(obraz, null, new Rect(x0 + xs, y0, x0 + dx + xs, y0 + dy), paint); //zmienione!!!
            }

            //płot
            //paint.Color = Color.Argb(255,150,75,0);
            //paint.Color = Resources.GetColor(Resource.Color.brazowy); //obsolete
            paint.Color = new Color(Android.Support.V4.Content.ContextCompat.GetColor(Context, Resource.Color.brazowy));
            {
                int x0 = szerokość / 15;
                int y0 = 6 * wysokość / 10;
                int dx = szerokość / 25;
                int y1 = 9 * wysokość / 10;
                canvas.DrawRect(new Rect(x0, y0 + dx, szerokość - x0 - dx, y0 + 3 * dx / 2), paint);
                canvas.DrawRect(new Rect(x0, y1 - 3 * dx / 2, szerokość - x0 - dx, y1 - dx), paint);
                for (int x = x0; x <= szerokość - x0 - dx; x += x0)
                {
                    canvas.DrawRect(new Rect(x, y0, x + dx, y1), paint);
                    canvas.DrawArc(new RectF(new Rect(x, y0 - dx / 2, x + dx, y0 + dx / 2)), 180, 180, true, paint); //te wszystkie obiekty nie powinny byc tu inicjowane
                }
            }

            //napis
            paint.Color = Color.Black;
            paint.StrokeWidth = 0.3f;
            paint.TextSize = 30f;
            //string tekst = "(c) Jacek Matulewski 2018";

            double interwał = aktualnyCzas - poprzedniCzas;
            interwał /= 1000; //[ms] -> [s]
            double fi = Java.Lang.Math.Round(100 / interwał) / 100.0;
            string tekst = "FPS: " + string.Format("{0:00.00}", fi); //f w [Hz]=[1/s]=[FPS]            

            float w = paint.MeasureText(tekst);
            float margines = wysokość / 30;
            canvas.DrawText(tekst, szerokość - w - margines, wysokość - margines, paint);

            //ślad palca (wskażnik)
            if (czyKursorWidoczny)
            {
                paint.Color = Color.Black;
                paint.StrokeWidth = 1f;
                paint.SetStyle(Paint.Style.Stroke);
                canvas.DrawCircle(kursor.X, kursor.Y, kursorPromien, paint);
            }

            //multitouch - urzadzenie musi to wspierac!
            if (czyKursorWidoczny && kursory.Count > 0)
            {
                paint.Color = Color.Red;
                paint.StrokeWidth = 1f;
                paint.SetStyle(Paint.Style.Stroke);
                for (int i = 0; i < kursory.Count; ++i)
                {
                    canvas.DrawCircle(kursory[i].X, kursory[i].Y, 2 * kursorPromien, paint);
                    string numer = i.ToString();
                    Rect rozmiar = new Rect(); paint.GetTextBounds(numer, 0, numer.Length, rozmiar);
                    canvas.DrawText(numer, kursory[i].X - rozmiar.Width() / 2f, kursory[i].Y + rozmiar.Height() / 2f, paint);
                }
            }

            Invalidate(); //animacja, wymuszamy kolejne wywolanie OnDraw - nie do końca eleganckie, lepiej timer
        }

        #region Dotyk
        private PointF kursor = new PointF(0, 0);
        private const float kursorPromien = 15;
        private bool czyKursorWidoczny = false;
        private List<PointF> kursory = new List<PointF>();

        public override bool OnTouchEvent(MotionEvent e)
        {
            MotionEventActions akcja = e.Action & MotionEventActions.Mask;
            switch (akcja)
            {
                case MotionEventActions.Down:
                case MotionEventActions.PointerDown:
                    czyKursorWidoczny = true;
                    break;
                case MotionEventActions.Up:
                case MotionEventActions.PointerUp:
                    czyKursorWidoczny = false;
                    break;
            }

            kursor.X = e.GetX();
            kursor.Y = e.GetY();

            int ileKursorów = e.PointerCount;
            kursory.Clear();
            for (int i = 0; i < ileKursorów; ++i)
                kursory.Add(new PointF(e.GetX(i), e.GetY(i)));

            //return base.OnTouchEvent(e);
            return true;
        }
        #endregion
    }
}