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

using Android.App;
using Android.Content;
using Android.Graphics;
using Android.OS;
using Android.Runtime;
using Android.Util;
using Android.Views;
using Android.Widget;

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

        public MainActivityView(Context context, IAttributeSet attrs) :
            base(context, attrs)
        {
            Initialize();
        }

        public MainActivityView(Context context, IAttributeSet attrs, int defStyle) :
            base(context, attrs, defStyle)
        {
            Initialize();
        }

        private void Initialize()
        {
            paint = new Paint(PaintFlags.AntiAlias);            

            szerokość = this.Width;
            wysokość = this.Height;
            Log.Debug("view.ctor", "szerokość: " + szerokość);
            Log.Debug("view.ctor", "wysokość: " + wysokość);

            SetBackgroundColor(Color.Cyan);
        }

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

            szerokość = this.Width;
            wysokość =  this.Height;
            Log.Debug("view.onSizeChanged", "szerokość: " + szerokość);
            Log.Debug("view.onSizeChanged", "wysokość: " + wysokość);

            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.onSizeChanged", "Obraz nie został wczytany");
        }

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

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

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

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

            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 + (float)(r2 * Java.Lang.Math.Cos(wsp * i)), y0 + (float)(r2 * System.Math.Sin(wsp * i)), paint);
                }
            }

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

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

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

            int _x0 = 13 * szerokość / 40;
            int _y0 = 2 * wysokość / 5;
            paint.Color = Color.Cyan;
            for (int ix = 0; ix < 2; ++ix)
                for (int iy = 0; iy < 2; ++iy)
                {
                    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);
                }

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

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

            double f = 0.001;

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

            }

            paint.Color = Color.Black;
            paint.StrokeWidth = 0.3f;
            paint.TextSize = 30f;
            //string tekst = "Uniwersytet Mikołaja Kopernika";

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

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

            //Dotyk i wielodotyk
            if (czyKursorWidoczny)
            {
                paint.Color = Color.Black;
                paint.StrokeWidth = 1f;
                paint.SetStyle(Paint.Style.Stroke);
                canvas.DrawCircle(kursor.X, kursor.Y, kursorPromień, paint);

                if(kursory.Count > 0)
                {
                    paint.Color = Color.Red;
                    for(int i = 0; i < kursory.Count; ++i)
                    {
                        canvas.DrawCircle(kursory[i].X, kursory[i].Y, 2 * kursorPromień, 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();
        }

        #region Dotyk
        private PointF kursor = new PointF(0, 0);
        private const float kursorPromień = 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();

            //wielodotyk
            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 true;
        }
        #endregion
    }
}