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

//the namespace must be PAT.Lib, the class and method names can be arbitrary
namespace PAT.Lib
{
    /// <summary>
    /// You can use static library in PAT model.
    /// All methods should be declared as public static.
    /// 
    /// The parameters must be of type "int", "bool", "int[]" or user defined data type
    /// The number of parameters can be 0 or many
    /// 
    /// The return type can be void, bool, int, int[] or user defined data type
    /// 
    /// The method name will be used directly in your model.
    /// e.g. call(max, 10, 2), call(dominate, 3, 2), call(amax, [1,3,5]),
    /// 
    /// Note: method names are case sensetive
    /// </summary>
    public class Example
    {
        //==========================================================
        //the following sections are the functions used by Mailbox 
        //==========================================================
        private static List<int[]> Matrix;

        //dominate(v,w) == CHOOSE x \in 1..7 : GT(x, v) /\ GT(x, w)
        public static int dominate(int v, int w)
        {
            for (int i = 1; i <= 7; i++)
            {
                if (matrix[i - 1][v - 1] == 1 && matrix[i - 1][w - 1] == 1)
                {
                    return i;
                }
            }
            return -1;
        }

        //GT(v,w) == (Edges[v][w]=1)
        public static bool mailorder(int v, int w)
        {
            return matrix[v - 1][w - 1] == 1; 
        }

        private static List<int[]> matrix
        {
            get
            {
                if (Matrix == null)
                {
                    Matrix = new List<int[]>(7);
                    Matrix.Add(new int[] {0, 0, 1, 1, 1, 0, 0});
                    Matrix.Add(new int[] {1, 0, 1, 0, 0, 0, 1});
                    Matrix.Add(new int[] {0, 0, 0, 0, 1, 1, 1});
                    Matrix.Add(new int[] {0, 1, 1, 0, 0, 1, 0});
                    Matrix.Add(new int[] {0, 1, 0, 1, 0, 0, 1});
                    Matrix.Add(new int[] {1, 1, 0, 0, 1, 0, 0});
                    Matrix.Add(new int[] {1, 0, 0, 1, 0, 1, 0});
                }
                return Matrix;
            }
        }

        //==========================================================
        //the following sections are the functions used by Bakery  
        //The maximum value of the array will be returned.
        //==========================================================
        public static int amax(int[] values)
        {
            int max = values[0];
            foreach (int v in values)
            {
                if(max < v)
                {
                    max = v;
                }
            }
            return max;
        }

        public static int asum1(int[] values, int startingIndex)
        {
            int sum = 0;
            int dimention = (int) Math.Sqrt(values.Length);
            for (int i = 0; i < dimention; i++)
            {
                sum += values[startingIndex + i];
            }
            return sum;
        }

        public static int asum2(int[] values, int startingIndex)
        {
            int sum = 0;
            int dimention = (int)Math.Pow(values.Length, 1.0 / 3.0); ;
            for (int i = 0; i < dimention; i++)
            {
                sum += values[startingIndex + i];
            }
            return sum;
        }

        /// <summary>
        /// Multi-lift example to check whether life i can make a move on the given level and direction
        /// </summary>
        /// <param name="level"></param>
        /// <param name="direction"></param>
        /// <param name="i"></param>
        /// <param name="NoOfFloors"></param>
        /// <param name="intrequests"></param>
        /// <param name="extrequestsUP"></param>
        /// <param name="extrequestsDOWN"></param>
        /// <returns></returns>
        public static bool CheckIfToMove(int level, int direction, int i, int NoOfFloors, int[] intrequests, int[] extrequestsUP, int[] extrequestsDOWN)
        {
            int Counter = level + direction;
            while (Counter >= 0 && Counter < NoOfFloors)
            {
                if (extrequestsUP[Counter] != 0 || extrequestsDOWN[Counter] != 0 || intrequests[i * NoOfFloors + Counter] != 0)
                {
                    return true;
                }
                else
                {
                    Counter = Counter + direction;
                }
            }
            return false;
        }

    }
}
