using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using BankTV.Consts;
using BankTV.Logger;
using System.Web;
using System.Net;
using BankTV.Weather;

namespace BankTV.Helpers.Weather
{
    class WeatherApiHelper
    {
        private static string GetWeatherFilePath(string fileName)
        {
            try
            {
                if (String.IsNullOrEmpty(fileName))
                {
                    return null;
                }   //if
                string weatherFolder = GlobalHelper.GetWeatherFolder();
                if (String.IsNullOrEmpty(weatherFolder))
                {
                    throw new Exception("Unable to get app config folder.");
                }   //if
                return System.IO.Path.Combine(weatherFolder, fileName);
            }   //try
            catch (Exception ex)
            {
                MyLogger.Log(ex);
                return null;
            }   //catch
        }

        private static string GetTempWeatherFilePath(string fileName)
        {
            try
            {
                if (String.IsNullOrEmpty(fileName))
                {
                    return null;
                }   //if
                string weatherFolder = GlobalHelper.GetWeatherFolder();
                if (String.IsNullOrEmpty(weatherFolder))
                {
                    throw new Exception("Unable to get app config folder.");
                }   //if
                fileName = fileName + GlobalConsts.TMP_EXTENSION;
                return System.IO.Path.Combine(weatherFolder, fileName);
            }   //try
            catch (Exception ex)
            {
                MyLogger.Log(ex);
                return null;
            }   //catch
        }

        private static bool DownloadWeatherFile(string fileName, string url)
        {
            if (String.IsNullOrEmpty(fileName))
            {
                return false;
            }   //if
            if (String.IsNullOrEmpty(url))
            {
                return false;
            }   //if
            try
            {
                string weatherFile = WeatherApiHelper.GetWeatherFilePath(fileName);
                string tempWeatherFile = WeatherApiHelper.GetTempWeatherFilePath(fileName);
                if ((String.IsNullOrEmpty(weatherFile)) || (String.IsNullOrEmpty(tempWeatherFile)))
                {
                    throw new Exception(String.Format("Unable to get weather file {0}", fileName));
                }   //if
                if (File.Exists(tempWeatherFile))
                {
                    File.Delete(tempWeatherFile);
                }   //if
                WebClient webClient = new WebClient();
                webClient.DownloadFile(url, tempWeatherFile);
                if (File.Exists(tempWeatherFile))
                {
                    if (File.Exists(weatherFile))
                    {
                        File.Replace(tempWeatherFile, weatherFile, weatherFile + ".bak");
                    }   //if
                    else
                    {
                        File.Copy(tempWeatherFile, weatherFile);
                        File.Delete(tempWeatherFile);
                    }   //else
                }   //if                
                return true;
            }   //try
            catch (Exception ex)
            {
                MyLogger.Log(ex);
                return false;
            }   //catch
        }

        private static bool WriteWeatherCityFile(string city)
        {
            if (String.IsNullOrEmpty(city))
            {
                return false;
            }   //if
            try
            {
                string url = String.Format("http://api.openweathermap.org/data/2.5/weather?units=metric&q={0}&mode=xml&APPID={1}", Uri.EscapeUriString(city), GlobalConsts.WEATHER_API_KEY);                
                return WeatherApiHelper.DownloadWeatherFile(GlobalConsts.WEATHER_CITY_FILE, url);
            }   //try
            catch (Exception ex)
            {
                MyLogger.Log(ex);
                return false;
            }   //catch
        }

        private static bool WriteWeatherCityFile(string city, string fileName)
        {
            if (String.IsNullOrEmpty(city))
            {
                return false;
            }   //if
            if (String.IsNullOrEmpty(fileName))
            {
                return false;
            }   //if
            try
            {
                string url = String.Format("http://api.openweathermap.org/data/2.5/weather?units=metric&q={0}&mode=xml&APPID={1}", Uri.EscapeUriString(city), GlobalConsts.WEATHER_API_KEY);
                return WeatherApiHelper.DownloadWeatherFile(fileName, url);
            }   //try
            catch (Exception ex)
            {
                MyLogger.Log(ex);
                return false;
            }   //catch
        }

        private static bool WriteForecastCityFile(string city)
        {
            if (String.IsNullOrEmpty(city))
            {
                return false;
            }   //if
            try
            {
                string url = String.Format("http://api.openweathermap.org/data/2.5/forecast/daily?units=metric&q={0}&mode=xml&cnt=7&APPID={1}", Uri.EscapeUriString(city), GlobalConsts.WEATHER_API_KEY);
                return WeatherApiHelper.DownloadWeatherFile(GlobalConsts.WEATHER_FORECAST_FILE, url);
            }   //try
            catch (Exception ex)
            {
                MyLogger.Log(ex);
                return false;
            }   //catch
        }

        public static bool UpdateWeather(string city)
        {
            if (String.IsNullOrEmpty(city))
            {
                return false;
            }   //if
            try
            {
                if (!WeatherApiHelper.CheckIsUrlValid("http://openweathermap.org/"))
                {
                    return true;
                }   //if
                if (!WeatherApiHelper.WriteWeatherCityFile(city))
                {
                    throw new Exception(String.Format("Unable to get current weather for the city {0}", city));
                }   //if
                if (!WeatherApiHelper.WriteForecastCityFile(city))
                {
                    throw new Exception(String.Format("Unable to get weather forecast for the city {0}", city));
                }   //if
                if (!WeatherApiHelper.WriteWeatherCityFile(GlobalConsts.WEATHER_GDANSK_CITY, GlobalConsts.WEATHER_GDANSK_FILE))
                {
                    throw new Exception(String.Format("Unable to get weather forecast for the city {0}", city));
                }   //if
                if (!WeatherApiHelper.WriteWeatherCityFile(GlobalConsts.WEATHER_POZNAN_CITY, GlobalConsts.WEATHER_POZNAN_FILE))
                {
                    throw new Exception(String.Format("Unable to get weather forecast for the city {0}", city));
                }   //if
                if (!WeatherApiHelper.WriteWeatherCityFile(GlobalConsts.WEATHER_RZESZOW_CITY, GlobalConsts.WEATHER_RZESZOW_FILE))
                {
                    throw new Exception(String.Format("Unable to get weather forecast for the city {0}", city));
                }   //if
                if (!WeatherApiHelper.WriteWeatherCityFile(GlobalConsts.WEATHER_SZCZECIN_CITY, GlobalConsts.WEATHER_SZCZECIN_FILE))
                {
                    throw new Exception(String.Format("Unable to get weather forecast for the city {0}", city));
                }   //if
                if (!WeatherApiHelper.WriteWeatherCityFile(GlobalConsts.WEATHER_WARSZAWA_CITY, GlobalConsts.WEATHER_WARSZAWA_FILE))
                {
                    throw new Exception(String.Format("Unable to get weather forecast for the city {0}", city));
                }   //if
                if (!WeatherApiHelper.WriteWeatherCityFile(GlobalConsts.WEATHER_WROCLAW_CITY, GlobalConsts.WEATHER_WROCLAW_FILE))
                {
                    throw new Exception(String.Format("Unable to get weather forecast for the city {0}", city));
                }   //if
                if (!WeatherApiHelper.WriteWeatherCityFile(GlobalConsts.WEATHER_BIALYSTOK_CITY, GlobalConsts.WEATHER_BIALYSTOK_FILE))
                {
                    throw new Exception(String.Format("Unable to get weather forecast for the city {0}", city));
                }   //if
                return true;
            }   //try
            catch (Exception ex)
            {
                MyLogger.Log(ex);
                return false;
            }   //catch
        }

        private static bool CheckIsUrlValid(string url)
        {
            if (String.IsNullOrWhiteSpace(url))
            {
                return false;
            }   //if
            HttpWebResponse response = null;
            var request = (HttpWebRequest)WebRequest.Create(url);
            request.Method = "HEAD";
            try
            {
                response = (HttpWebResponse)request.GetResponse();
            }
            catch
            {
                return false;
            }
            finally
            {            
                if (response != null)
                {
                    response.Close();
                }   //if
            }   //finally
            return true;
        }
    }

}
