// Copyright 2014 by Sascha L. Teichmann
// Use of this source code is governed by the MIT license
// that can be found in the LICENSE file.

package main

import (
	"flag"
	"fmt"
	"log"
	"net"
	"net/http"

	"bitbucket.org/s_l_teichmann/mtsatellite/common"

	"github.com/gorilla/mux"
)

func main() {
	var (
		webPort     int
		webHost     string
		webDir      string
		mapDir      string
		redisPort   int
		redisHost   string
		colorsFile  string
		workers     int
		transparent bool
		updateHosts string
		websockets  bool
		playersFIFO string
	)
	flag.IntVar(&webPort, "web-port", 8808, "port of the web server")
	flag.IntVar(&webPort, "p", 8808, "port of the web server (shorthand)")
	flag.StringVar(&webHost, "web-host", "localhost", "address to bind web server")
	flag.StringVar(&webHost, "h", "localhost", "address to bind web server(shorthand)")
	flag.StringVar(&webDir, "web", "web", "static served web files.")
	flag.StringVar(&webDir, "w", "web", "static served web files (shorthand)")
	flag.StringVar(&mapDir, "map", "map", "directory of prerendered tiles")
	flag.StringVar(&mapDir, "m", "map", "directory of prerendered tiles (shorthand)")
	flag.StringVar(&updateHosts, "update-hosts", "localhost",
		"';' separated list of hosts which are allowed to send map update requests")
	flag.StringVar(&updateHosts, "u", "localhost",
		"';' separated list of hosts which are allowed to send map update requests (shorthand)")
	flag.StringVar(&redisHost, "redis-host", "", "address of the backend Redis server")
	flag.StringVar(&redisHost, "rh", "", "address of the backend Redis server (shorthand)")
	flag.IntVar(&redisPort, "redis-port", 6379, "port of the backend Redis server")
	flag.IntVar(&redisPort, "rp", 6379, "port of the backend Redis server (shorthand)")
	flag.IntVar(&workers, "workers", 1, "number of workers to render tiles")
	flag.StringVar(&colorsFile, "colors", "colors.txt", "colors used to render map tiles.")
	flag.StringVar(&colorsFile, "c", "colors.txt", "colors used to render map tiles (shorthand).")
	flag.BoolVar(&transparent, "transparent", false, "Render transparent blocks.")
	flag.BoolVar(&transparent, "t", false, "Render transparent blocks (shorthand).")
	flag.BoolVar(&websockets, "websockets", false, "Forward tile changes to clients via websockets.")
	flag.BoolVar(&websockets, "ws", false, "Forward tile changes to clients via websockets (shorthand).")
	flag.StringVar(&playersFIFO, "players", "", "Path to FIFO file to read active players from.")
	flag.StringVar(&playersFIFO, "ps", "", "Path to FIFO file to read active players from (shorthand).")

	flag.Parse()

	router := mux.NewRouter()

	subBaseLine := newSubBaseLine(mapDir)
	router.Path("/map/{z:[0-9]+}/{x:[0-9]+}/{y:[0-9]+}.png").Handler(subBaseLine)

	var btu baseTilesUpdates
	var wsf *websocketForwarder

	if websockets {
		wsf = newWebsocketForwarder()
		go wsf.run()
		router.Path("/ws").Methods("GET").Handler(wsf)
		btu = wsf
	}

	if playersFIFO != "" {
		plys := newPlayers(playersFIFO, wsf)
		go plys.run()
		router.Path("/players").Methods("GET").Handler(plys)
	}

	if redisHost != "" {
		var colors *common.Colors
		var err error
		if colors, err = common.ParseColors(colorsFile); err != nil {
			log.Fatalf("ERROR: problem loading colors: %s", err)
		}
		redisAddress := fmt.Sprintf("%s:%d", redisHost, redisPort)

		var allowedUpdateIps []net.IP
		if allowedUpdateIps, err = ipsFromHosts(updateHosts); err != nil {
			log.Fatalf("ERROR: name resolving problem: %s", err)
		}

		tu := newTileUpdater(
			mapDir,
			redisAddress,
			allowedUpdateIps,
			colors,
			transparent,
			workers,
			btu)
		go tu.doUpdates()
		router.Path("/update").Methods("POST").Handler(tu)
	}

	router.PathPrefix("/").Handler(http.FileServer(http.Dir(webDir)))
	http.Handle("/", router)

	addr := fmt.Sprintf("%s:%d", webHost, webPort)
	if err := http.ListenAndServe(addr, nil); err != nil {
		log.Fatalf("Starting server failed: %s\n", err)
	}
}