using System;
using AgkSharp;
using AGKCore;

namespace Terrain
{

    static class Program
    {
        /// <summary>
        /// Der Haupteinstiegspunkt für die Anwendung.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Core.CreateWin32Window("AGK-Title", 640, 480, false);
            if (!Core.InitAGK())
                return;

            // set window properties
            Agk.SetWindowTitle("Terrain");
            Agk.SetWindowSize(1024, 768, 0);
            Agk.SetWindowAllowResize(1);
            Agk.SetSyncRate(0, 0);
            Agk.SetAntialiasMode(1);

            // set display properties
            Agk.SetVirtualResolution(1024, 768);
            Agk.SetOrientationAllowed(1, 1, 1, 1);
            Agk.SetScissor(0, 0, 0, 0);
            Agk.SetCameraRange(1, 0.1f, 2000);

            // enable the sky box
            Agk.SetSkyBoxVisible(1);

            // load terrain detail texture with mipmapping enabled
            Agk.SetGenerateMipmaps(1);
            Agk.LoadImage(1, "media/detail.png");
            Agk.SetImageWrapU(1, 1);
            Agk.SetImageWrapV(1, 1);

            // load the terrain shader to give the terrain color based on height
            Agk.LoadShader(1, "media/Terrain.vs", "media/Terrain.ps");

            // create the terrain object from a height map
            Agk.CreateObjectFromHeightMap(1, "media/US Rockies.png", 768, 50, 768, 1, 16);
            Agk.SetObjectImage(1, 1, 0);
            Agk.SetObjectUVScale(1, 0, 128, 128); // scale the detail texture so it repeats
            Agk.SetObjectShader(1, 1);

            Agk.SetCameraPosition(1, 383, 30, 383);
            Agk.SetCameraLookAt(1, 0, 40, 0, 0);

            Agk.SetAmbientColor(128, 128, 128);

            // buttons for mobile devices to control the camera 
            Agk.AddVirtualButton(1, Agk.GetScreenBoundsRight() - 45, Agk.GetScreenBoundsBottom() - 45, 80);
            Agk.AddVirtualButton(2, Agk.GetScreenBoundsRight() - 45, Agk.GetScreenBoundsBottom() - 130, 80);
            Agk.AddVirtualButton(3, Agk.GetScreenBoundsLeft() + 45, Agk.GetScreenBoundsBottom() - 45, 80);

            Agk.SetPrintSize(15);

            // add some atmospheric fog
            Agk.SetFogMode(1);
            Agk.SetFogColor(161, 183, 209);
            Agk.SetFogRange(50, 700);
            Agk.SetFogSunColor(255, 230, 179);

            // camera starts in free mode
            int cameraMode = 0;
            float time = 0.0f;
            float startx = 0.0f;
            float starty = 0.0f;
            float angx = 0.0f;
            float angy = 0.0f;
            float fDiffX = 0.0f;
            float fDiffY = 0.0f;
            float newX = 0.0f;
            while (Core.LoopAGK())
            {
                // move the camera
                float speed = 1.0f;
                if (Agk.GetRawKeyState(16) != 0) speed = 0.1f;
                if (cameraMode == 1) speed = 0.25f;


                if (Agk.GetRawKeyState(87) != 0) Agk.MoveCameraLocalZ(1, speed);
                if (Agk.GetRawKeyState(83) != 0) Agk.MoveCameraLocalZ(1, -speed);


                if (Agk.GetRawKeyState(65) != 0) Agk.MoveCameraLocalX(1, -speed);
                if (Agk.GetRawKeyState(68) != 0) Agk.MoveCameraLocalX(1, speed);


                if (Agk.GetRawKeyState(81) != 0) Agk.MoveCameraLocalY(1, -speed);
                if (Agk.GetRawKeyState(69) != 0) Agk.MoveCameraLocalY(1, speed);


                if (Agk.GetVirtualButtonState(1) == 1) Agk.MoveCameraLocalZ(1, -speed);
                if (Agk.GetVirtualButtonState(2) == 1) Agk.MoveCameraLocalZ(1, speed);

                // rotate the camera
                //int pressed = 1;
                if (Agk.GetPointerPressed() != 0)
                {
                    startx = Agk.GetPointerX();
                    starty = Agk.GetPointerY();
                    angx = Agk.GetCameraAngleX(1);
                    angy = Agk.GetCameraAngleY(1);
                    //pressed = 1;
                }

                if (Agk.GetPointerState() == 1)
                {
                    fDiffX = (Agk.GetPointerX() - startx) / 4.0f;
                    fDiffY = (Agk.GetPointerY() - starty) / 4.0f;

                    newX = angx + fDiffY;
                    if (newX > 89.0f) newX = 89.0f;
                    if (newX < -89.0f) newX = -89.0f;
                    Agk.SetCameraRotation(1, newX, angy + fDiffX, 0);
                }

                // change camera mode
                if (Agk.GetVirtualButtonPressed(3) == 1) cameraMode = 1 - cameraMode;
                if (cameraMode == 1)
                {
                    float x, z;
                    // stick camera to the terrain
                    x = Agk.GetCameraX(1);
                    z = Agk.GetCameraZ(1);

                    Agk.SetCameraPosition(1, x, Agk.GetObjectHeightMapHeight(1, x, z) + 0.5f, z);
                }

                // move the sun 
                time = time + Agk.GetFrameTime() * 0.5f;
                float xdir = Agk.Sin(time);
                float ydir = -0.5f;
                float zdir = Agk.Cos(time);
                Agk.SetSunDirection(xdir, ydir, zdir);

                // show some information
                Agk.Print("FPS: " + Agk.ScreenFPS().ToString("N1"));
                Agk.Print("Polygons: " + Agk.GetPolygonsDrawn().ToString());

                Agk.Sync();
            }

            Core.CleanUp();
        }
    }
}
