/*
 * Copyright (c) 2016 Samsung Electronics Co., Ltd
 *
 * Licensed under the Flora License, Version 1.1 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://floralicense.org/license/
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

using System;
using Xamarin.Forms;

namespace Puzzle
{
    class AnsPage : ContentPage
    {
        /// <summary>
        /// The Answer page, if ansBtn clicked, will push this page to front.
        /// Only contain a whole answer image in center.
        /// </summary>
        public AnsPage()
        {
            Content = new Image
            {
                Source = "smile.jpg",
                HorizontalOptions = LayoutOptions.CenterAndExpand,
                VerticalOptions = LayoutOptions.CenterAndExpand,
                WidthRequest = 600,
                HeightRequest = 600,
            };
        }
    }

    /// <summary>
    /// Puzzle app's Main page, UI part.
    /// Puzzle main page contain 3 views:
    /// 1. Menu view on top.
    /// 2. Puzzle view in the middle.
    /// 3. Control button view at the bottom.
    /// </summary>
    public partial class PuzzlePage : ContentPage
    {
        private View _menuGrid;
        private Grid _puzzleGrid;
        private View _controlBtnGrid;

        /// <summary>
        /// Create Menu View in the top of main layout.
        /// </summary>
        /// <returns>return a Grid layout</returns>
        private View CreateMenuGrid()
        {
            //The main Grid contain 3 menu item.
            Grid grid = new Grid()
            {
                HorizontalOptions = LayoutOptions.FillAndExpand,
                VerticalOptions = LayoutOptions.FillAndExpand,
                ColumnSpacing = 10,
                RowSpacing = 10,
                HeightRequest = 160,

            };

            /* ------------  Answer menu ------------ */
            Button ansBtn = new Button()
            {
                Image =  "photo.png",
                HorizontalOptions = LayoutOptions.CenterAndExpand,
                VerticalOptions = LayoutOptions.CenterAndExpand,
                WidthRequest = 100,
                HeightRequest = 100,
            };
            //Add this view in first low, first column.
            grid.Children.Add(ansBtn, 0, 1, 0, 1);

            //Register button click event
            ansBtn.Clicked += (sender, e) =>
            {
                Navigation.PushModalAsync(new AnsPage());
            };

            /* ------------  Level menu ------------ */
            Button levBtn = new Button()
            {
                Image = "level.png",
                HorizontalOptions = LayoutOptions.CenterAndExpand,
                VerticalOptions = LayoutOptions.CenterAndExpand,
                WidthRequest = 100,
                HeightRequest = 100,
            };
            //Add this view in first low, second column.
            grid.Children.Add(levBtn, 1, 2, 0, 1);

            levBtn.Clicked += (sender, e) =>
            {
                if (_level == PuzzleLevel.Level2)
                {
                    _level = PuzzleLevel.Level1;
                    CreatePuzzle(_puzzleGrid);
                }
                else
                {
                    _level = PuzzleLevel.Level2;
                    CreatePuzzle(_puzzleGrid);
                }
            };

            /* ------------  Refresh menu ------------ */
            Button refBtn = new Button()
            {
                Image = "shuffle.png",
                HorizontalOptions = LayoutOptions.CenterAndExpand,
                VerticalOptions = LayoutOptions.CenterAndExpand,
                WidthRequest = 100,
                HeightRequest = 100,
            };
            //Add this view in first low, third column.
            grid.Children.Add(refBtn, 2, 3, 0, 1);
            
            refBtn.Clicked += (sender, e) =>
            {
                Random ran = new Random();
                //Refresh puzzle by moving blocks at random in REFRESH_FACTOR times.
                for (int i = 0; i < REFRESH_FACTOR; i++)
                {
                    Direction direct = (Direction)(ran.Next(0, 1000) % 4);
                    int directX, directY;
                    switch (direct)
                    {
                    case Direction.LEFT:
                        directX = -1;
                        directY = 0;
                        break;
                    case Direction.RIGHT:
                        directX = 1;
                        directY = 0;
                        break;
                    case Direction.UP:
                        directX = 0;
                        directY = -1;
                        break;
                    default:
                        directX = 0;
                        directY = 1;
                        break;
                    }

                    foreach (var de in _images)
                    {
                        Position pos = (Position)de.Value;
                        if (pos.X + directX == _blankPos.X && pos.Y + directY == _blankPos.Y)
                        {
                            MoveBlock((Image)de.Key, pos, direct);
                            break;
                        }
                    }
                }
            };

            return grid;
        }

        /// <summary>
        /// Add image blocks in puzzle view
        /// </summary>
        /// <param name="grid">The container Grid layout</param>
        private void CreatePuzzle(Grid grid)
        {
            int level = (int)_level;
            int imageSize = 225;
            int size = imageSize / level;

            //Clear Grid items, _images collection firstly
            grid.Children.Clear();
            _images.Clear();
            //The blank block's position at the right bottom corner.
            _blankPos = new Position(level - 1, level - 1);

            Image imgEx = null;
            for (int i = 0; i < level; i++)
            {
                for (int j = 0; j < level; j++)
                {
                    //Does not add Image in blank block.
                    if (i == _blankPos.Y && j == _blankPos.X)
                    {
                        break;
                    }

                    imgEx = new Image()
                    {
                        Source = "smile.jpg",
                        HorizontalOptions = LayoutOptions.CenterAndExpand,
                        VerticalOptions = LayoutOptions.CenterAndExpand,
                        MinimumWidthRequest = (720 - 2 * 2 * level) / level,
                        MinimumHeightRequest = (720 - 2 * 2 * level) / level,
                    };

                    _images.Add(imgEx, new Position(j, i));

                    //Add created Image object to Grid
                    grid.Children.Add(imgEx, j, j + 1, i, i + 1);
                }
            }
        }

        /// <summary>
        /// Create puzzle view in middle of main layout
        /// </summary>
        /// <returns>return a Grid layout</returns>
        private Grid CreatePuzzleGrid()
        {
            Grid grid = new Grid()
            {
                HorizontalOptions = LayoutOptions.FillAndExpand,
                VerticalOptions = LayoutOptions.FillAndExpand,
                ColumnSpacing = 2,
                RowSpacing = 2,
                HeightRequest = 680,
            };

            CreatePuzzle(grid);

            return grid;
        }

        /// <summary>
        /// Create control button view at the bottom of main layout
        /// </summary>
        /// <returns>return a Grid layout</returns>
        private View CreateControlBtnGrid()
        {
            Grid grid = new Grid()
            {
                HorizontalOptions = LayoutOptions.FillAndExpand,
                VerticalOptions = LayoutOptions.FillAndExpand,
                ColumnSpacing = 10,
                RowSpacing = 10,
                HeightRequest = 280,
            };

            Button btn = new Button()
            {
                Text = "LEFT",
                HorizontalOptions = LayoutOptions.FillAndExpand,
                VerticalOptions = LayoutOptions.FillAndExpand,
            };

            btn.Clicked += (sender, e) =>
            {
                //Check which block can be moved to left.
                foreach (var de in _images)
                {
                    Position pos = (Position)de.Value;
                    if (pos.X - 1 == _blankPos.X && pos.Y == _blankPos.Y)
                    {
                        MoveBlock((Image)de.Key, pos, Direction.LEFT);
                        break;
                    }
                }
            };
            //Layout button to Grid's 1~2 column, 1~2 row.
            grid.Children.Add(btn, 0, 2, 0, 2);

            btn = new Button()
            {
                Text = "UP",
                HorizontalOptions = LayoutOptions.FillAndExpand,
                VerticalOptions = LayoutOptions.FillAndExpand,
            };

            btn.Clicked += (sender, e) =>
            {
                //Check which block can be moved to top.
                foreach (var de in _images)
                {
                    Position pos = (Position)de.Value;
                    if (pos.X == _blankPos.X && pos.Y - 1 == _blankPos.Y)
                    {
                        MoveBlock((Image)de.Key, pos, Direction.UP);
                        break;
                    }
                }
            };
            //Layout button to Grid's 3~4 column, 1 row.
            grid.Children.Add(btn, 2, 4, 0, 1);

            btn = new Button()
            {
                Text = "DOWN",
                HorizontalOptions = LayoutOptions.FillAndExpand,
                VerticalOptions = LayoutOptions.FillAndExpand,
            };

            btn.Clicked += (sender, e) =>
            {
                //Check which block can be moved down.
                foreach (var de in _images)
                {
                    Position pos = (Position)de.Value;
                    if (pos.X == _blankPos.X && pos.Y + 1 == _blankPos.Y)
                    {
                        MoveBlock((Image)de.Key, pos, Direction.DOWN);
                        break;
                    }
                }
            };
            //Layout button to Grid's 3~4 column, 2 row.
            grid.Children.Add(btn, 2, 4, 1, 2);

            btn = new Button()
            {
                Text = "RIGHT",
                HorizontalOptions = LayoutOptions.FillAndExpand,
                VerticalOptions = LayoutOptions.FillAndExpand,
            };

            btn.Clicked += (sender, e) =>
            {
                //Check which block can be moved to right.
                foreach (var de in _images)
                {
                    Position pos = (Position)de.Value;
                    if (pos.X + 1 == _blankPos.X && pos.Y == _blankPos.Y)
                    {
                        MoveBlock((Image)de.Key, pos, Direction.RIGHT);
                        break;
                    }
                }
            };
            //Layout button to Grid's 5~6 column, 1~2 row.
            grid.Children.Add(btn, 4, 6, 0, 2);
            return grid;
        }

        /// <summary>
        /// Create UI components.
        /// </summary>
        void InitializeComponent()
        {
            Title = "Puzzle";

            _menuGrid = CreateMenuGrid();

            _puzzleGrid = CreatePuzzleGrid();

            _controlBtnGrid = CreateControlBtnGrid();

            //Create main container
            StackLayout mainLayout = new StackLayout()
            {
                IsVisible = true,
                HorizontalOptions = LayoutOptions.FillAndExpand,
                VerticalOptions = LayoutOptions.FillAndExpand,
                Orientation = StackOrientation.Vertical,
                Padding = new Thickness(5),
                Children = {_menuGrid, _puzzleGrid, _controlBtnGrid },
            };

            Content = mainLayout;

        }

    }

}
