package main

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

	"battlecamp-go-server/events"
	"battlecamp-go-server/flag"
	"battlecamp-go-server/player"
	"battlecamp-go-server/stomp"
)

func main() {
	initLogging()
	log.Println("Game bot version 0.1")

	flag.ParseFlags()
	pu := make(chan *events.PlayerUpdate)
	go subscribeToUpdate(pu)
	subscribeToGame(pu)
}

func subscribeToGame(pu chan *events.PlayerUpdate) {
	sub := stomp.Subscribe("game")

	for {
		announcement := <-sub
		gs := new(events.GameStart)
		json.Unmarshal(announcement.Body, &gs)
		log.Printf("announcement type: %v ", strconv.FormatInt(gs.GameId, 10))
		gameEndChan := make(chan bool)
		if "GAME_START" == gs.Type {
			go joinGame(gs.GameId, gameEndChan, pu)
		} else {
			gameEndChan <- true
		}
	}
}

func subscribeToUpdate(pu chan *events.PlayerUpdate) {
	sub := stomp.Subscribe("update")

	for {
		announcement := <-sub
		if "vnd.battlecamp.player" == announcement.ContentType {
			p := new(player.Player)
			json.Unmarshal(announcement.Body, &p)
			playerJoin(p)
		} else {
			pue := new(events.PlayerUpdate)
			json.Unmarshal(announcement.Body, &pue)
			pu <- pue
		}
	}
}

func joinGame(gameId int64, gameEndChan chan bool, pu chan *events.PlayerUpdate) {
	//join game
	p := &player.Player{
		Id:    "Zeus",
		Color: "#238b02",
		Type:  1,
	}
	
	players := make([]*player.Player, 5)

	url := "http://localhost:8080/games/" + strconv.FormatInt(gameId, 10) + "/join"

	jsonStr, _ := json.Marshal(p)
	req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonStr))
	req.Header.Set("Content-Type", "application/json")
	fmt.Println("URL:>", req)
	
	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		panic(err)
	}
	v, _ := ioutil.ReadAll(resp.Body)
	json.Unmarshal(v, p) 
	resp.Body.Close()

	for {
		select {
		case <-gameEndChan:
			return
		case playerUpdate := <- pu:
			if(playerUpdate.GameId == gameId) {
				players = playerUpdate.Players
				for _, pup := range players {
					if(pup.Id == p.Id) {
						p.Pos.X = pup.Pos.X
						p.Pos.Y = pup.Pos.Y
						fmt.Printf("Set position to x=%v y=%v\n", pup.Pos.X, pup.Pos.Y)
					}
				}
			}
		default:
			move(gameId, p, players)
			time.Sleep(2 * time.Second)
		}
	}
}

func move(gameId int64, p *player.Player, players []*player.Player) {
	//retrieve viewport
	
	//determine move
	direction := "E"
	
	//send move
	url := "http://localhost:8080/games/" + strconv.FormatInt(gameId, 10) + "/move/" + p.Id + "/" + direction
	fmt.Println("move:>", url)
	
	http.Post(url, "text/plain", nil)
	
	//update x,y
	switch direction {
		case "N":
			p.Pos.Y++
		case "E":
			p.Pos.X++
		case "S":
			p.Pos.Y--
		case "W":
			p.Pos.Y++
	}

}

func playerJoin(p *player.Player) {

}

func initLogging() {
	logFile, err := os.Create("server.log")

	if err == nil {
		log.SetOutput(logFile)
	} else {
		log.Println("ERROR: Cannot open log file, using console.")
		log.Printf("%v=n", err)
	}
}
