package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"time"

	"github.com/fatih/color"
	"github.com/kyokomi/emoji"
)

type WeatherAPI struct {
	Coord      Coord     `json:"coord"`
	Weather    []Weather `json:"weather"`
	Base       string    `json:"base"`
	Main       Main      `json:"main"`
	Visability int64     `json:"visibility"`
	Wind       Wind      `json:"wind"`
	Rain       Rain      `json:"rain"`
	Clouds     Cloud     `json:"cloud"`
	DT         int64     `json:"dt"`
	Sys        Sys       `json:"sys"`
	TimeZone   int       `json:"timezone"`
	ID         int       `json:"id"`
	Name       string    `json:"name"`
	COD        int       `json:"cod"`
}

type Coord struct {
	Lon float64 `json:"lon"`
	Lat float64 `json:"lat"`
}

type Weather struct {
	ID          int    `json:"id"`
	Main        string `json:"main"`
	Description string `json:"description"`
	Icon        string `json:"icon"`
}

type Main struct {
	Temp       float64 `json:"temp"`
	Feels_like float64 `json:"feels_like"`
	Temp_min   float64 `json:"temp_min"`
	Temp_max   float64 `json:"temp_max"`
	Pressure   float64 `json:"pressure"`
	Humidity   float64 `json:"humidity"`
}

type Wind struct {
	Speed float64 `json:"speed"`
	Deg   float64 `json:"deg"`
	Gust  float64 `json:"gust"`
}

type Rain struct {
	T1h float64 `json:"1h"`
}

type Cloud struct {
	All int `json:"all"`
}

type Sys struct {
	Types   int    `json:"type"`
	Id      int64  `json:"id"`
	Country string `json:"country"`
	Sunrise int64  `json:"sunrise"`
	Sunset  int64  `json:"sunset"`
}

func main() {
	//set up the flags for the program to use!
	var city, code, api_key string
	flag.StringVar(&city, "city", "London", "Enter city e.g. London, Glasgow etc... (Default: London)")
	flag.StringVar(&code, "code", "uk", "Enter Code e.g. uk, us etc... (Default: uk)")
	flag.StringVar(&api_key, "api", "none", "Enter Code e.g. uk, us etc... Default(none)")
	flag.Parse()

	full := "https://api.openweathermap.org/data/2.5/weather?q=" + city + "," + code + "&units=metric" + "&appid=" + api_key + ""

	//read webpage
	html, _ := loadWebPage(full)

	//Create file
	createFile(string(html), false)

	//Load the file
	data, _ := loadJson("weather.json")

	//Print the weather!
	printWeather(data)
}

func loadJson(file string) (WeatherAPI, error) {
	var config WeatherAPI
	configFile, err := os.Open(file)
	if err != nil {
		fmt.Println(err.Error())
	}
	jsonParser := json.NewDecoder(configFile)
	jsonParser.Decode(&config)
	return config, err
}

func createFile(fileContents string, debugFlag bool) {
	file, err := os.Create("weather.json")
	if err != nil {
		log.Fatalf("failed creating file: %s", err)
	}

	defer file.Close()

	len, err := file.WriteString(fileContents)
	if err != nil {
		log.Fatalf("failed writing to file: %s", err)
	}

	// Debug Flag
	if debugFlag {
		fmt.Printf("\nFile Name: %s", file.Name())
		fmt.Printf("\nLength: %d bytes", len)
	}
}

func loadWebPage(web_url string) ([]byte, error) {
	url := web_url
	resp, err := http.Get(url)
	//reads html as a slice of bytes
	html, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		panic(err)
	}
	return html, err

}

func iconToEmoji(icon string) {
	var em string
	switch icon {
	case "Clouds":
		em = ":cloud:"
	case "Drizzle":
		em = ":rain:"
	case "Rain":
		em = ":rain:"
	case "Snow":
		em = ":snow:"
	case "Clear":
		em = ":sun:"
	default:
		em = ":sun"
	}
	emoji.Printf(em)
}

func printWeather(data WeatherAPI) {
	weatherData := data

	dt := time.Now()
	fmt.Println(dt.Format("01/02/2006 15:04"))

	white := color.New(color.FgWhite)
	boldWhite := white.Add(color.Bold)

	str_loc := weatherData.Name
	str_code := weatherData.Sys.Country
	str_weather := weatherData.Weather[0].Main
	str_weather_detail := weatherData.Weather[0].Description
	str_weather_icon := weatherData.Weather[0].Main
	str_temp := weatherData.Main.Temp
	str_temp_fl := weatherData.Main.Feels_like
	str_temp_min := weatherData.Main.Temp_min
	str_temp_max := weatherData.Main.Temp_max
	str_sunset := time.Unix(weatherData.Sys.Sunset, 0)
	str_sunrise := time.Unix(weatherData.Sys.Sunrise, 0)

	boldWhite.Printf("Location: ")
	fmt.Printf("%v, %v\n", str_loc, str_code)
	boldWhite.Printf("Weather: ")
	iconToEmoji(str_weather_icon)
	fmt.Printf(" %v (%v)\n", str_weather, str_weather_detail)
	boldWhite.Printf("Temp: ")
	fmt.Printf("%v°C (Feels like: %v°C)\n(Min: %v°C, Max: %v°C)\n", str_temp, str_temp_fl, str_temp_min, str_temp_max)
	boldWhite.Printf("Sunrise: ")
	fmt.Printf("%v\t", str_sunrise.Format("15:04"))
	boldWhite.Printf("Sunset: ")
	fmt.Printf("%v\n", str_sunset.Format("15:04"))
}
