// 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 (
	"image/color"
	"log"
	"os"
	"path/filepath"
	"strconv"
	"sync"

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

const (
	baseLevelDir = "8"
)

type blockPos struct {
	x, z int16
	j, i int
}

func createTiles(
	btc *common.BaseTileCreator,
	jobs chan blockPos,
	done *sync.WaitGroup) {

	wFns := make(chan func() (bool, error))

	// Writing already rendered tiles to disk can be done in background.
	go func() {
		for wfn := range wFns {
			if _, err := wfn(); err != nil {
				log.Printf("WARN: writing file failed: %v.\n", err)
			}
		}
	}()

	defer func() {
		close(wFns)
		btc.Close()
		done.Done()
	}()

	for job := range jobs {
		if err := btc.RenderArea(job.x-1, job.z-1); err != nil {
			log.Printf("WARN: rendering failed: %v.\n", err)
			continue
		}
		wFns <- btc.WriteFunc(job.i, job.j, nil)
	}
}

func createBaseLevel(
	dbcf common.DBClientFactory,
	xMin, yMin, zMin, xMax, yMax, zMax int,
	transparent bool, transparentDim float32,
	colorsFile string, bg color.RGBA, outDir string,
	numWorkers int) (err error) {

	var colors *common.Colors

	if colors, err = common.ParseColors(colorsFile); err != nil {
		return
	}

	colors.TransparentDim = transparentDim

	baseDir := filepath.Join(outDir, baseLevelDir)
	if err = os.MkdirAll(baseDir, os.ModePerm); err != nil {
		return
	}

	jobs := make(chan blockPos)
	var done sync.WaitGroup

	for i := 0; i < numWorkers; i++ {
		var client common.DBClient

		if client, err = dbcf.Create(); err != nil {
			return
		}
		done.Add(1)
		btc := common.NewBaseTileCreator(
			client, colors, bg,
			int16(yMin), int16(yMax),
			transparent, baseDir)
		go createTiles(btc, jobs, &done)
	}

	zMin, zMax = common.Order(zMin, zMax)

	for x, i := int16(xMin), 0; x <= int16(xMax); x += 16 {
		xDir := filepath.Join(baseDir, strconv.Itoa(i))
		log.Printf("creating dir: %s\n", xDir)
		if err = os.MkdirAll(xDir, os.ModePerm); err != nil {
			log.Fatalf("Cannot create directory '%s': %s\n", xDir, err)
		}
		for z, j := int16(zMin), 0; z <= int16(zMax); z += 16 {
			jobs <- blockPos{x: x, z: z, i: i, j: j}
			j++
		}
		i++
	}
	close(jobs)

	done.Wait()

	return
}