package web

import (
	"encoding/json"
	"fmt"
	"git.ssns.se/git/frozendragon/pokemon-go-trade/internal/pokemon"
	"github.com/sirupsen/logrus"
	"github.com/spf13/viper"
	"io/ioutil"
	"net/http"
	"strconv"
)

type WebPackage struct {
	Config  *viper.Viper
	Log     *logrus.Logger
	Pokemon pokemon.Interface
}

type PokemonsWantResponse struct {
	ID        int       `json:"id"`
	GroupName string    `json:"group_name"`
	Pokemons  []Pokemon `json:"pokemons"`
}

type PokemonsResponse struct {
	Pokemons []Pokemon `json:"pokemons"`
}

type Pokemon struct {
	ID  int    `json:"id"`
	Url string `json:"url"`
}

type DeleteStoredPokemonWantRequest struct {
	ID int `json:"id"`
}

var availablePokemonResponse = PokemonsResponse{
	Pokemons: []Pokemon{},
}

var pokemonsWantResponse = []PokemonsWantResponse{
	{
		ID:        1,
		GroupName: "want group 1",
		Pokemons:  availablePokemonResponse.Pokemons,
	},
}

func (wp *WebPackage) GetAvailablePokemon(w http.ResponseWriter, r *http.Request) {
	availablePokemonResponse, err := wp.Pokemon.GetAvailablePokemons()
	if err != nil {
		w.WriteHeader(500)
		_, _ = w.Write([]byte(err.Error()))
		return
	}

	bodyBytes, err := json.Marshal(availablePokemonResponse)
	if err != nil {
		w.WriteHeader(500)
		_, _ = w.Write([]byte(err.Error()))
		return
	}

	w.WriteHeader(200)
	_, _ = w.Write(bodyBytes)
}

func (wp *WebPackage) PostStoredPokemon(w http.ResponseWriter, r *http.Request) {
	bodyBytes, err := ioutil.ReadAll(r.Body)
	if err != nil {
		w.WriteHeader(500)
		_, _ = w.Write([]byte(err.Error()))
		return
	}

	var Pokemon []Pokemon
	err = json.Unmarshal(bodyBytes, &Pokemon)
	if err != nil {
		w.WriteHeader(500)
		_, _ = w.Write([]byte(err.Error()))
		return
	}

	if r.URL.Query().Get("type") == "want" {
		wantGroupIDString := r.URL.Query().Get("want-group-id")
		wantGroupID, err := strconv.Atoi(wantGroupIDString)
		if err != nil {
			w.WriteHeader(500)
			_, _ = w.Write([]byte(err.Error()))
			return
		}

		pokemonsWantResponse[wantGroupID-1].Pokemons = append(pokemonsWantResponse[wantGroupID-1].Pokemons, Pokemon...)
	} else {
		availablePokemonResponse.Pokemons = append(availablePokemonResponse.Pokemons, Pokemon...)
	}

	w.WriteHeader(200)
	_, _ = w.Write(bodyBytes)
}

type LinkedStoredPokemonResponse struct {
	Links []LinkedStoredPokemonRequest `json:"links"`
}

type LinkedStoredPokemonRequest struct {
	GroupID    int `json:"group_id"`
	SelectedID int `json:"selected_id"`
}

var linkedStoredPokemonResponse = LinkedStoredPokemonResponse{
	Links: []LinkedStoredPokemonRequest{},
}

func (wp *WebPackage) GetLinkedStoredPokemon(w http.ResponseWriter, r *http.Request) {
	bodyBytes, err := json.Marshal(linkedStoredPokemonResponse)
	if err != nil {
		w.WriteHeader(500)
		_, _ = w.Write([]byte(err.Error()))
		return
	}

	w.WriteHeader(200)
	_, _ = w.Write(bodyBytes)
}

func (wp *WebPackage) PostLinkedStoredPokemon(w http.ResponseWriter, r *http.Request) {
	bodyBytes, err := ioutil.ReadAll(r.Body)
	if err != nil {
		w.WriteHeader(500)
		_, _ = w.Write([]byte(err.Error()))
		return
	}

	var link LinkedStoredPokemonRequest
	err = json.Unmarshal(bodyBytes, &link)
	if err != nil {
		w.WriteHeader(500)
		_, _ = w.Write([]byte(err.Error()))
		return
	}

	linkedStoredPokemonResponse.Links = append(linkedStoredPokemonResponse.Links, link)

	bodyBytes, err = json.Marshal(linkedStoredPokemonResponse)
	if err != nil {
		w.WriteHeader(500)
		_, _ = w.Write([]byte(err.Error()))
		return
	}

	w.WriteHeader(200)
	_, _ = w.Write(bodyBytes)
}

func (wp *WebPackage) GetStoredPokemonHave(w http.ResponseWriter, r *http.Request) {
	bodyBytes, err := json.Marshal(availablePokemonResponse)
	if err != nil {
		w.WriteHeader(500)
		_, _ = w.Write([]byte(err.Error()))
		return
	}

	w.WriteHeader(200)
	_, _ = w.Write(bodyBytes)
}

func (wp *WebPackage) GetStoredPokemonWant(w http.ResponseWriter, r *http.Request) {
	bodyBytes, err := json.Marshal(pokemonsWantResponse)
	if err != nil {
		w.WriteHeader(500)
		_, _ = w.Write([]byte(err.Error()))
		return
	}

	w.WriteHeader(200)
	_, _ = w.Write(bodyBytes)
}

func (wp *WebPackage) CreateStoredPokemonWant(w http.ResponseWriter, r *http.Request) {
	pokemonsWantResponse = append(pokemonsWantResponse, PokemonsWantResponse{
		ID:        len(pokemonsWantResponse),
		GroupName: fmt.Sprintf("want group %d", len(pokemonsWantResponse)),
		Pokemons:  []Pokemon{},
	})

	bodyBytes, err := json.Marshal(pokemonsWantResponse)
	if err != nil {
		w.WriteHeader(500)
		_, _ = w.Write([]byte(err.Error()))
		return
	}

	w.WriteHeader(200)
	_, _ = w.Write(bodyBytes)
}

func (wp *WebPackage) DeleteStoredPokemonWant(w http.ResponseWriter, r *http.Request) {
	bodyBytes, err := ioutil.ReadAll(r.Body)
	if err != nil {
		w.WriteHeader(500)
		_, _ = w.Write([]byte(err.Error()))
		return
	}

	var deleteStoredPokemonWantRequest DeleteStoredPokemonWantRequest
	err = json.Unmarshal(bodyBytes, &deleteStoredPokemonWantRequest)
	if err != nil {
		w.WriteHeader(500)
		_, _ = w.Write([]byte(err.Error()))
		return
	}

	pokemonsWantResponse = append(pokemonsWantResponse[:deleteStoredPokemonWantRequest.ID-1], pokemonsWantResponse[deleteStoredPokemonWantRequest.ID:]...)

	bodyBytes, err = json.Marshal(pokemonsWantResponse)
	if err != nil {
		w.WriteHeader(500)
		_, _ = w.Write([]byte(err.Error()))
		return
	}

	w.WriteHeader(200)
	_, _ = w.Write(bodyBytes)
}
