// Copyright 2014, 2015 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 (
	"encoding/json"
	"log"
	"net/http"
	"sync"

	"bytes"

	"bitbucket.org/s_l_teichmann/mtsatellite/common"
)

// Pull up if it _really_ produces too much data.
const quantizationFactor = 1

type quantizedXZ struct {
	X, Z int16
}

type changeTracker struct {
	changes map[quantizedXZ]bool
	mutex   sync.Mutex
}

func newChangeTracker() *changeTracker {
	return &changeTracker{changes: make(map[quantizedXZ]bool)}
}

func (ct *changeTracker) BlockChanged(coord common.Coord) {
	ct.mutex.Lock()
	ct.changes[quantizedXZ{
		X: coord.X / quantizationFactor,
		Z: coord.Z / quantizationFactor}] = true
	ct.mutex.Unlock()
}

func (ct *changeTracker) FlushChanges(url string) {
	var oldChanges map[quantizedXZ]bool
	ct.mutex.Lock()
	if len(ct.changes) > 0 {
		oldChanges = ct.changes
		ct.changes = make(map[quantizedXZ]bool)
	}
	ct.mutex.Unlock()
	if oldChanges == nil {
		return
	}
	go func() {
		changes := make([]quantizedXZ, len(oldChanges))
		i := 0
		for change := range oldChanges {
			changes[i] = change
			i++
		}
		var err error
		var buf bytes.Buffer
		encoder := json.NewEncoder(&buf)
		if err = encoder.Encode(changes); err != nil {
			log.Printf("WARN: encode changes to JSON failed: %s\n", err)
			return
		}
		var resp *http.Response
		resp, err = http.Post(
			url, "application/json", bytes.NewBuffer(buf.Bytes()))
		if resp != nil {
			defer resp.Body.Close()
		}
		if err != nil {
			log.Printf("WARN: posting changes to %s failed: %s\n", url, err)
		}
	}()
	return
}