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

namespace MapClient
{
    // this class is between application and IMapCenterServiceservice - class communicating with map cerver     // ewentualnie do przeróbki
    public class IMapService
    {
        // data needed to create connection to server 
        private readonly string serverName;                                     // full server address and port
        private readonly string userName; 
        private readonly string userPassword;

        private IMapCenterServiceservice serviceSOAP;                           // an object to communicate with map server using SOAP.
        private TSoapCreateSessionID__mcsResult sessionId;
        private TSoapGetAvailableImageFormats__mcsResult imageFormats;          // available image formats in which we can download maps
        private TSoapGetDefaultLayers__mcsResult layers;                        // available map layers
        private TSoapGetProjections__mcsResult projections;                     // available types of projection
        private bool sessionAlive;
        private TSoapGetSessionLifetimeSeconds__mcsResult sessionLifetime;      // sessions lifetime

        // the only one constructor
        public IMapService(string _serverName, string _userName, string _userPassword)
        {
            serverName = _serverName;
            userName = _userName;
            userPassword = _userPassword;
            sessionAlive = false;
        }

        // this method connects to map server, returns true when succeded
        public bool beginSession()
        {
            try
            {
                // creating a connection to server
                serviceSOAP = new IMapCenterServiceservice(serverName,userName,userPassword); 
                sessionId = serviceSOAP.CreateSessionID();
                
                sessionAlive = true;
            }
            catch (System.Net.WebException)                                   // cannot establish connection to a server
            {
                sessionAlive = false;
                return false;
            }

            // getting available image formats from map server
            imageFormats = serviceSOAP.GetAvailableImageFormats();
            if (imageFormats.SoapResult != 1)
            {
                closeSession();
                return false;
            }

            // getting available layers from map server
            layers = serviceSOAP.GetDefaultLayers(sessionId.SessionID);
            if (layers.SoapResult != 1)
            {
                closeSession();
                return false;
            }

            // getting available projections from map server
            projections = serviceSOAP.GetProjections();
            if (projections.SoapResult != 1)
            {
                closeSession();
                return false;
            }

            sessionLifetime = serviceSOAP.GetSessionLifetimeSeconds();
            if (sessionLifetime.SoapResult != 1)
            {
                closeSession();
                return false;
            }
            
            return true;
        }

        // This function is to close server session.
        public bool closeSession()
        {
            if (!sessionAlive) 
            {
                return true;
            }
            sessionAlive = false; 

            return (serviceSOAP.DropSession(sessionId.SessionID) == 1);
        }
        
        // This function downloads map rendered by middle point of a map
        public TSoapRenderMapOnImageByPoint__mcsResult renderByPoint(MapParameters mapParameters, TSoapTLongLatPoint longLatPoint, int width, int height)
        {
            string mapProjecitionParam = "";//for future use

            // creating an object with rendering parameters
            TSoapTImageRenderParams imageRenderParams = new TSoapTImageRenderParams();
            imageRenderParams.RenderWithoutSessionObjects = false;
            imageRenderParams.Antialiasing = true;
            imageRenderParams.DPI = mapParameters.DPI;

            // function returns map for requested user's parameters
            return serviceSOAP.RenderMapOnImageByPoint(
                   sessionId.SessionID,
                   imageFormats.ImageFormats[0],                                   
                   longLatPoint,
                   mapParameters.Altitude,
                   mapParameters.Rotation,
                   mapParameters.Tilt,
                   mapParameters.TypeOfProjection,
                   mapProjecitionParam,
                   width,
                   height,
                   mapParameters.VisibleLayers,
                   imageRenderParams
                   );
        }

        // This function downloads map rendered by rectangle with given top-left and bottom-right points.
        public TSoapRenderMapOnImageByRect__mcsResult renderByRect(MapParameters mapParameters,TSoapTLongLatRect longLatRec , int Width, int Height)
        {
            string mapProjecitionParam = "";                                               
            
            // creating an object with rendering parameters
            TSoapTImageRenderParams imageRenderParams = new TSoapTImageRenderParams();
            imageRenderParams.RenderWithoutSessionObjects = false;
            imageRenderParams.Antialiasing = true;
            imageRenderParams.DPI = mapParameters.DPI;

            // function returns map for requested user's parameters
            return serviceSOAP.RenderMapOnImageByRect(
                   sessionId.SessionID,
                   imageFormats.ImageFormats[0],                                   
                   longLatRec.TopLeft,
                   longLatRec.BottomRight,
                   mapParameters.Rotation,
                   mapParameters.Tilt,
                   mapParameters.TypeOfProjection,
                   mapProjecitionParam,
                   Width,
                   Height,
                   mapParameters.VisibleLayers,
                   imageRenderParams
                   );
        }
        
        // This function clears map from added items to server session          
        public void clearMapFromAddItem()
        {
            serviceSOAP.ClearMapSelection(sessionId.SessionID);
        }
         
        public string[] getAvailableLayers()
        {
            return layers.MapLayers;
        }
        
        public string[] getAvailableProjections()
        {
            return projections.Projections;
        }
         
        public bool isSessionAlive()
        {
            return sessionAlive;
        }
        
        //This function is to initialize search module.
        public int searchInitialize()
        {
            int initialize = serviceSOAP.SearchInitialize(sessionId.SessionID, false);
            return initialize;
        }

        //This funtion is to find searching city on server.
        public int searchForCity(string cityName)
        {
            TSoapSearchGetCountryList__mcsResult countryList = serviceSOAP.SearchGetCountryList(sessionId.SessionID);

            int country = 0;                // 0 means any country - see documentation
            string zipCode = "";
            string administrativeArea1 = "";
            string administrativeArea2 = "";
            string administrativeArea3 = "";

            if (countryList.SoapResult == 1)
            {
                TSoapSearchSelectCities__mcsResult foundCities = serviceSOAP.SearchSelectCities(
                    sessionId.SessionID,
                    country,
                    cityName,
                    zipCode,
                    administrativeArea1,
                    administrativeArea2,
                    administrativeArea3
                    );

                return foundCities.ResultCount;
            }
            else
            {
                return 0;
            }
        }

        //This function gets detailed information about found cities
        public TSoapSearchGetCityList__mcsResult getFoundCityList(int citiesCount)
        {
            int first = 0;              

            TSoapSearchGetCityList__mcsResult foundCities = serviceSOAP.SearchGetCityList(
                sessionId.SessionID,
                first,
                citiesCount
                );

            return foundCities;
        }
        
        // This function marks found city on a map.
        public TSoapSearchAddCityToSelection__mcsResult addingCity(int whichCity)
        {
            TSoapSearchAddCityToSelection__mcsResult addingCity = serviceSOAP.SearchAddCityToSelection(
                sessionId.SessionID,
                whichCity
                );

            return addingCity;
        }

        // This method searchs for a street in found city.
        public int searchForStreet(int inWhichCity, string streetName)
        {   

                int itemKindIndex = 6;              //setting kind of item on street - see documentation
               
                TSoapSearchSelectItems__mcsResult selectedItem = serviceSOAP.SearchSelectItems(
                    sessionId.SessionID,
                    inWhichCity,
                    itemKindIndex, 
                    streetName
                    );

                return selectedItem.ResultCount;

        }

        // This function returns detailed information about found street.
        public TSoapSearchGetItemsList__mcsResult foundStreet(int streetCount)
        {
            int first = 0;

            TSoapSearchGetItemsList__mcsResult streetList = serviceSOAP.SearchGetItemsList(
                sessionId.SessionID,
                first,
                streetCount
                );

            return streetList;
        }

        // This function marks found street on a map.
        public TSoapSearchAddObjectToSelection__mcsResult addStreet(int whichStreet)
        {
            TSoapSearchAddObjectToSelection__mcsResult addingStreet = serviceSOAP.SearchAddObjectToSelection(
                sessionId.SessionID, whichStreet);
            
            return addingStreet;
        }

        // This function marks found street with number on a map.
        public TSoapSearchAddStreetWithNumToSelection__mcsResult addStreetWithNum(int whichStreet, string num)
        {
            TSoapSearchAddStreetWithNumToSelection__mcsResult addingStreetWithNum = serviceSOAP.SearchAddStreetWithNumToSelection(
                sessionId.SessionID, whichStreet, num);

            return addingStreetWithNum;
        }

        // This function converts screen points to geographical coordinates
        public TSoapConvertScreenToMap__mcsResult pointsConverting(MapParameters mapParameters, int height, int width, TSoapTLongLatPoint middlePoint, TSoapTPoint[] pointsForConverting)
        {
            TSoapTImageRenderParams imageRenderParams = new TSoapTImageRenderParams();

            imageRenderParams.RenderWithoutSessionObjects = true;
            imageRenderParams.Antialiasing = false;
            imageRenderParams.DPI = mapParameters.DPI;
            
            string mapProjectionParam = "";                                   //for future use

            TSoapConvertScreenToMap__mcsResult pointsConverted = serviceSOAP.ConvertScreenToMap(
                sessionId.SessionID,
                middlePoint,
                mapParameters.Altitude,
                mapParameters.Rotation,
                mapParameters.Tilt,
                mapParameters.TypeOfProjection,
                mapProjectionParam,
                width,
                height,
                imageRenderParams,
                pointsForConverting
                );

            return pointsConverted;    
        }

        // This function is to geocode objects on a map.
        public TSoapGeocode__mcsResult geocoding(string[] words)
        {
            TSoapTGeocodePointInfo[] pointsForGeokoding = new TSoapTGeocodePointInfo[words.Length / 7];

            int j = 0;

            for (int i = 0; i < pointsForGeokoding.Length; i++)
            {
                TSoapTGeocodePointInfo point = new TSoapTGeocodePointInfo();
                point.Country = words[j];
                point.County = words[j + 1];
                point.District =  words[j + 2];
                point.City = words[j + 3];
                point.Zip = words[j + 4];
                point.Street = words[j + 5];
                point.StreetNumber = words[j + 6];
                j = j + 7;
                pointsForGeokoding[i] = point;
            }

            TSoapGeocode__mcsResult geocodeResult = serviceSOAP.Geocode(sessionId.SessionID,
                false,
                pointsForGeokoding);

            return geocodeResult;

        }

        // This function is to add localized object to a map serwer. An object can be marked using circle or icon.
        public int localize()
        {
            TSoapTFontParameters fontParameters = new TSoapTFontParameters();           //an object containing font parameters
            fontParameters.Charset = 1;
            fontParameters.Name = "";
            fontParameters.Size = 12;
            fontParameters.Style = 2;

            int entityID = 0;                           //object ID
            string name = "";                           //name of an object
            bool showName = false;                      //if the name should be shown on a map
            int iconID = 0;                             //if you use your icon to marked objects, so you need its ID
            bool showIcon = false;                      //if the icon should be shown on a map 
            int iconColour = 0;                         //colour of an icon in RGB
            int pathColour = 255;                       //colour of a path
            int pathWidth = 0;                          //width of a path
            int size = 5;                               //size of a points on a map
            bool removePreviousPositions = false;       //whether to remove previous positions
            bool pointsConnected = false;               //whether to make a path from points 
            bool showDirection = false;                 //whether to show out direction

            int localization = serviceSOAP.LocalizeObjectAdd(
                sessionId.SessionID,
                entityID,
                name,
                showName,
                iconID,
                showIcon,
                iconColour,
                pathColour,
                pathWidth,
                size,
                removePreviousPositions,
                pointsConnected,
                showDirection,
                fontParameters);

            return localization;
        }

        // This function adds position to a created object.
        public int localizeAddPosition(TSoapTLongLatPoint[] position)
        {
            TSoapTLocalizeObjectPositionData[] localizeData = new TSoapTLocalizeObjectPositionData[position.Length];
           
            for (int i = 0; i < localizeData.Length; i++)
            {
                TSoapTLocalizeObjectPositionData localizeDataTmp = new TSoapTLocalizeObjectPositionData();
                localizeDataTmp.Description = "";
                localizeDataTmp.IconColor = 0;
                localizeDataTmp.PositionPoint = position[i];
                localizeDataTmp.ShowIcon = false;
                localizeDataTmp.ShowDescription = false;
                localizeDataTmp.ShowName = false;
                localizeDataTmp.Time = 0;
                localizeData[i] = localizeDataTmp;
            }

            string[][] stringFild = new string[localizeData.Length][];
            double[][] floatFild = new double[localizeData.Length][];

            int addPosition = serviceSOAP.LocalizeAddObjectPositions(
                sessionId.SessionID,
                0,
                localizeData,
                stringFild,
                floatFild);
            
            return addPosition;
        }
    }
}
