using System;
using System.Runtime.InteropServices;
using AddinExpress.MSO;
 
namespace DINO_AddIn
{
    /// <summary>
    ///   Add-in Express Excel Add-in Module
    /// </summary>
    [GuidAttribute("2279B981-2F97-4A9E-BBB2-D3EEE050E52B"),
    ProgId("DINO WebService.DinoFunctionsModule"), ClassInterface(ClassInterfaceType.AutoDual)]
    public class DinoFunctionsModule : AddinExpress.MSO.ADXExcelAddinModule
    {
        public DinoFunctionsModule()
        {
            InitializeComponent();
        }
 
        #region Component Designer generated code
 
        /// <summary>
        /// Required by designer
        /// </summary>
        private System.ComponentModel.IContainer components;
 
        /// <summary>
        /// Required by designer support - do not modify
        /// the following method
        /// </summary>
        private void InitializeComponent()
        {
 
        }
 
        #endregion
 
        #region Add-in Express automatic code
 
        [ComRegisterFunctionAttribute]
        public static void AddinRegister(Type t)
        {
            AddinExpress.MSO.ADXExcelAddinModule.ADXExcelAddinRegister(t);
        }
 
        [ComUnregisterFunctionAttribute]
        public static void AddinUnregister(Type t)
        {
            AddinExpress.MSO.ADXExcelAddinModule.ADXExcelAddinUnregister(t);
        }
 
        #endregion

        //
        // Retrives the geoLayer name to the cell where the function is invoked
        // ej: =DINO_Layer_Name("gws21", 100, 163000, 400000, 1)
        //
        public Object DINO_Layer_Name(string model, int resolution, double x, double y, int layerIndex)
        {
            try{
                GeoColumn column = retrieveData(null, model, resolution, x, y);
                if (column != null)
                {
                    if (column.geoLayers.Length > layerIndex)
                    {
                        GeoLayer layer = column.geoLayers[layerIndex];
                        return layer.name;
                    }
                }
                return "NO DATA";
            }
            catch (Exception ee)
            {
                return errorProcessing(ee.Message);
            }
        }
        
        //
        // As the previous, but indicating web service URL
        // ej: =DINO_Layer_Name2("http://dinolab51.nitg.tno.nl/Geo3DModelWebservices-1.0/Geo3DModelService?wsdl","gws21", 100, 163000, 400000, 1)
        //
        public Object DINO_Layer_Name2(string serviceURL, string model, int resolution, double x, double y, int layerIndex)
        {
            try
            {
                GeoColumn column = retrieveData(serviceURL, model, resolution, x, y);
                if (column != null)
                {
                    if (column.geoLayers.Length > layerIndex)
                    {
                        GeoLayer layer = column.geoLayers[layerIndex];
                        return layer.name;
                    }
                }
                return "NO DATA";
            }
            catch (Exception ee)
            {
                return errorProcessing(ee.Message);
            }
        }

        //
        // Retrives the geoLayer code to the cell where the function is invoked
        // ej: =DINO_Layer_Code("gws21", 100, 163000, 400000, 1)
        //
        public Object DINO_Layer_Code(string model, int resolution, double x, double y, int layerIndex)
        {
            try
            {

                GeoColumn column = retrieveData(null, model, resolution, x, y);
                if (column != null)
                {
                    if (column.geoLayers.Length > layerIndex)
                    {
                        GeoLayer layer = column.geoLayers[layerIndex];
                        return layer.code;
                    }
                }
                return "NO DATA";
            }
            catch (Exception ee)
            {
                return errorProcessing(ee.Message);
            }
        }

        //
        // As the previous, but indicating web service URL
        // ej: =DINO_Layer_Code2("http://dinolab51.nitg.tno.nl/Geo3DModelWebservices-1.0/Geo3DModelService?wsdl","gws21", 100, 163000, 400000, 1)
        //
        public Object DINO_Layer_Code2(string serviceURL, string model, int resolution, double x, double y, int layerIndex)
        {
            try
            {

                GeoColumn column = retrieveData(serviceURL, model, resolution, x, y);
                if (column != null)
                {
                    if (column.geoLayers.Length > layerIndex)
                    {
                        GeoLayer layer = column.geoLayers[layerIndex];
                        return layer.code;
                    }
                }
                return "NO DATA";
            }
            catch (Exception ee)
            {
                return errorProcessing(ee.Message);
            }
        }

        //
        // Retrives the geoLayer top high to the cell where the function is invoked
        // ej: =DINO_Layer_Top("gws21", 100, 163000, 400000, 1)
        //
        public Object DINO_Layer_Top(string model, int resolution, double x, double y, int layerIndex)
        {
            try
            {

                GeoColumn column = retrieveData(null, model, resolution, x, y);
                if (column != null)
                {
                    if (column.geoLayers.Length > layerIndex)
                    {
                        GeoLayer layer = column.geoLayers[layerIndex];
                        return layer.top;
                    }
                }
                return "NO DATA";
            }
            catch (Exception ee)
            {
                return errorProcessing(ee.Message);
            }
        }

        //
        // As the previous, but indicating web service URL
        // ej: =DINO_Layer_Top2("http://dinolab51.nitg.tno.nl/Geo3DModelWebservices-1.0/Geo3DModelService?wsdl","gws21", 100, 163000, 400000, 1)
        //
        public Object DINO_Layer_Top2(string serviceURL, string model, int resolution, double x, double y, int layerIndex)
        {
            try
            {

                GeoColumn column = retrieveData(serviceURL, model, resolution, x, y);
                if (column != null)
                {
                    if (column.geoLayers.Length > layerIndex)
                    {
                        GeoLayer layer = column.geoLayers[layerIndex];
                        return layer.top;
                    }
                }
                return "NO DATA";
            }
            catch (Exception ee)
            {
                return errorProcessing(ee.Message);
            }
        }

        //
        // Retrives the geoLayer bottom high to the cell where the function is invoked
        // ej: =DINO_Layer_Bottom("gws21", 100, 163000, 400000, 1)
        //
        public Object DINO_Layer_Bottom(string model, int resolution, double x, double y, int layerIndex)
        {
            try
            {

                GeoColumn column = retrieveData(null, model, resolution, x, y);
                if (column != null)
                {
                    if (column.geoLayers.Length > layerIndex)
                    {
                        GeoLayer layer = column.geoLayers[layerIndex];
                        return layer.bottom;
                    }
                }
                return "NO DATA";
            }
            catch (Exception ee)
            {
                return errorProcessing(ee.Message);
            }
        }

        //
        // As the previous, but indicating web service URL
        // ej: =DINO_Layer_Bottom2("http://dinolab51.nitg.tno.nl/Geo3DModelWebservices-1.0/Geo3DModelService?wsdl","gws21", 100, 163000, 400000, 1)
        //
        public Object DINO_Layer_Bottom2(string serviceURL, string model, int resolution, double x, double y, int layerIndex)
        {
            try
            {

                GeoColumn column = retrieveData(serviceURL, model, resolution, x, y);
                if (column != null)
                {
                    if (column.geoLayers.Length > layerIndex)
                    {
                        GeoLayer layer = column.geoLayers[layerIndex];
                        return layer.bottom;
                    }
                }
                return "NO DATA";
            }
            catch (Exception ee)
            {
                return errorProcessing(ee.Message);
            }
        }

        //
        // Retrives a geoLayer parameter value to the cell where the function is invoked
        // ej: =DINO_Layer_Parameter("gws21", 100, 163000, 400000, 1, "Transmissiviteit(kD)")
        //
        public Object DINO_Layer_Parameter(string model, int resolution, double x, double y, int layerIndex, string parameterName)
        {
            try
            {

                GeoColumn column = retrieveData(null, model, resolution, x, y);
                if (column != null)
                {
                    if (column.geoLayers.Length > layerIndex)
                    {
                        GeoLayer layer = column.geoLayers[layerIndex];
                        if (layer.parameters != null)
                        {
                            foreach (GeoParameter p in layer.parameters)
                            {
                                if (p.name == parameterName) return p.value;

                            }
                        }
                        return "";
                    }
                }
                return "NO DATA";
            }
            catch (Exception ee)
            {
                return errorProcessing(ee.Message);
            }
        }

        //
        // As the previous, but indicating web service URL
        // ej: =DINO_Layer_Parameter2("http://dinolab51.nitg.tno.nl/Geo3DModelWebservices-1.0/Geo3DModelService?wsdl","gws21", 100, 163000, 400000, 1, "Transmissiviteit(kD)")
        //
        public Object DINO_Layer_Parameter2(string serviceURL, string model, int resolution, double x, double y, int layerIndex, string parameterName)
        {
            try
            {

                GeoColumn column = retrieveData(serviceURL, model, resolution, x, y);
                if (column != null)
                {
                    if (column.geoLayers.Length > layerIndex)
                    {
                        GeoLayer layer = column.geoLayers[layerIndex];
                        if (layer.parameters != null)
                        {
                            foreach (GeoParameter p in layer.parameters)
                            {
                                if (p.name == parameterName) return p.value;

                            }
                        }
                        return "";
                    }
                }
                return "NO DATA";
            }
            catch (Exception ee)
            {
                return errorProcessing(ee.Message);
            }
        }

        //
        // Function in charge of the web service call
        //
        private GeoColumn retrieveData(string serviceURL, string model, int resolution, double x, double y)
        {
            Geo3DModelService DinoService = new Geo3DModelService();

            if (serviceURL != null)
            {
                DinoService.Url = serviceURL;
            }
            
            GeoColumn response = DinoService.sampleColumn(model, x, y, resolution);
            return response;
        }

        //
        // Centralized error processing function
        //
        private string errorProcessing(string errorMessage)
        {
            //if (ee.Message.StartsWith("The request failed with", StringComparison.OrdinalIgnoreCase) || ee.Message.StartsWith("The remote name could not", StringComparison.OrdinalIgnoreCase))
            if (errorMessage.StartsWith("The request failed with HTTP status 503", StringComparison.OrdinalIgnoreCase))
                return "URL temporary unavailable";
            else if (errorMessage.StartsWith("The request failed with http status 404", StringComparison.OrdinalIgnoreCase) || errorMessage.StartsWith("Invalid URI", StringComparison.OrdinalIgnoreCase) || errorMessage.StartsWith("The remote name could not", StringComparison.OrdinalIgnoreCase))
                return "Invalid URL";
            else if (errorMessage.StartsWith("Er is geen model gevonden met code", StringComparison.OrdinalIgnoreCase))//Er is geen model gevonden met code 'gws2'.
                return "Wrong model name";
            else if (errorMessage.StartsWith("'Voor model", StringComparison.OrdinalIgnoreCase)) //'Voor model 'gws21 is geen resolutie '102' beschikbaar.
                return "Invalid resolution value";
            else if (errorMessage.StartsWith("'Er zijn voor model", StringComparison.OrdinalIgnoreCase)) //'Er zijn voor model 'ghm_zh' met resolutie '100' geen gegevens beschikbaar op deze locatie(163000.0,400000.0).
                return "Invalid coordinates for this model-resolution pair";
            else
                return "unknown error";
        }
    }
}

