func order() {
	requestURL := mapConfig.ServiceURL + "mapfile"
	requestString := fmt.Sprintf("{\n    \"Data\": {\n        \"Type\": \"maps\",\n        \"ID\": \"%s\"\n    }\n}", mapID)
	req, err := http.NewRequest("POST", requestURL, strings.NewReader(requestString))
	if err != nil {
		log.Fatalf("error <%v> at http.NewRequest()", err)
	}
	req.Header.Add("Content-Type", "application/vnd.api+json; charset=utf-8")
	req.Header.Add("Accept", "application/vnd.api+json; charset=utf-8")
	printRequest(req, true)
	resp, err := netClient.Do(req)
	if err != nil {
		log.Fatalf("error <%v> at http.Do()", err)
	}
	defer resp.Body.Close()
	printResponse(resp, true)
	printSuccess(resp, http.StatusAccepted)
}
/*
order places the map order
package main
import (
	"archive/zip"
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"mime/multipart"
	"net/http"
	"net/http/httputil"
	"os"
	"path/filepath"
	"strconv"
	"strings"
	"github.com/StefanSchroeder/Golang-Ellipsoid/ellipsoid"
	"github.com/davecgh/go-spew/spew"
	"github.com/im7mortal/UTM"
	"github.com/paulmach/orb"
	"github.com/paulmach/orb/geojson"
	"github.com/printmaps/printmaps/pd"
	lua "github.com/yuin/gopher-lua"
	yaml "gopkg.in/yaml.v2"
)
var (
	progName    = os.Args[0]
	progVersion = "v0.7.0"
	progDate    = "2021/06/12"
	progPurpose = "Printmaps Command Line Interface Client"
	progInfo    = "Creates large-sized maps in print quality."
)
type MapConfig struct {
	ServiceURL  string      `yaml:"ServiceURL"`
	Metadata    pd.Metadata `yaml:"Metadata,inline"`
	UploadFiles []string    `yaml:"UserFiles"`
}
var mapConfig MapConfig
var mapID string
var (
	mapDefinitionFile = "map.yaml"
	mapIDFile         = "map.id"
)
var netClient = &http.Client{}
func init() {
	log.SetFlags(log.Ldate | log.Ltime | log.Lmicroseconds | log.Lshortfile)
}
func main() {
	_, progName = filepath.Split(progName)
	if len(os.Args) == 1 {
		printUsage()
	}
	if _, err := os.Stat(mapDefinitionFile); err == nil {
		source, err := ioutil.ReadFile(mapDefinitionFile)
		if err != nil {
			log.Fatalf("error <%v> at ioutil.ReadFile(), file = <%s>", err, mapDefinitionFile)
		}
		err = yaml.Unmarshal(source, &mapConfig)
		if err != nil {
			log.Fatalf("error <%v> at yaml.Unmarshal()", err)
		}
	}
	fmt.Printf("\nurl = %v\n", mapConfig.ServiceURL)
	if _, err := os.Stat(mapIDFile); err == nil {
		filedata, err := ioutil.ReadFile(mapIDFile)
		if err != nil {
			log.Fatalf("error <%v> at ioutil.ReadFile(), file = <%s>", err, mapIDFile)
		}
		mapID = string(filedata)
	}
	fmt.Printf("map ID = %v\n", mapID)
	action := strings.ToLower(strings.Trim(os.Args[1], " ,"))
	fmt.Printf("action = %v\n", action)
	if action == "create" {
		checkMapDefinitionFile()
		create()
	} else if action == "update" {
		checkMapDefinitionFile()
		checkMapIDFile()
		update()
	} else if action == "upload" {
		checkMapDefinitionFile()
		checkMapIDFile()
		for _, file := range mapConfig.UploadFiles {
			upload(file)
		}
	} else if action == "state" {
		checkMapDefinitionFile()
		checkMapIDFile()
		fetch(action)
	} else if action == "order" {
		checkMapDefinitionFile()
		checkMapIDFile()
		order()
	} else if action == "download" {
		checkMapDefinitionFile()
		checkMapIDFile()
		download()
	} else if action == "data" {
		checkMapDefinitionFile()
		checkMapIDFile()
		fetch(action)
	} else if action == "delete" {
		checkMapDefinitionFile()
		checkMapIDFile()
		delete()
	} else if action == "capabilities" {
		fetch(action)
	} else if action == "unzip" {
		unzip()
	} else if action == "passepartout" {
		passepartout()
	} else if action == "rectangle" {
		rectangle()
	} else if action == "cropmarks" {
		cropmarks()
	} else if action == "latlongrid" {
		latlongrid()
	} else if action == "utmgrid" {
		utmgrid()
	} else if action == "latlon2utm" {
		latlon2utm()
	} else if action == "utm2latlon" {
		utm2latlon()
	} else if action == "bearingline" {
		bearingline()
	} else if action == "latlonline" {
		latlonline()
	} else if action == "utmline" {
		utmline()
	} else if action == "runlua" {
		runlua()
	} else {
		fmt.Printf("action <%v> not supported\n", action)
	}
	fmt.Printf("\n")
	os.Exit(0)
}
func checkMapDefinitionFile() {
	if _, err := os.Stat(mapDefinitionFile); os.IsNotExist(err) {
		fmt.Printf("\nERROR - PRECONDITION FAILED:\n")
		fmt.Printf("- the map definition file <%s> doesn't exists\n", mapDefinitionFile)
		os.Exit(1)
	}
}
func checkMapIDFile() {
	if _, err := os.Stat(mapIDFile); os.IsNotExist(err) {
		fmt.Printf("\nERROR - PRECONDITION FAILED:\n")
		fmt.Printf("- the map ID file <%s> doesn't exists\n", mapIDFile)
		fmt.Printf("- apply the 'create' action to create the file\n\n")
		os.Exit(1)
	}
}
func printUsage() {
	fmt.Printf("\nProgram:\n")
	fmt.Printf("  Name         : %s\n", progName)
	fmt.Printf("  Release      : %s - %s\n", progVersion, progDate)
	fmt.Printf("  Purpose      : %s\n", progPurpose)
	fmt.Printf("  Info         : %s\n", progInfo)
	fmt.Printf("\nUsage:\n")
	fmt.Printf("  %s <action>\n", progName)
	fmt.Printf("\nExample:\n")
	fmt.Printf("  %s create\n", progName)
	fmt.Printf("\nActions:\n")
	fmt.Printf("  Primary      : create, update, upload, order, state, download\n")
	fmt.Printf("  Secondary    : data, delete, capabilities\n")
	fmt.Printf("  Helper       : unzip\n")
	fmt.Printf("  Helper       : passepartout, rectangle, cropmarks\n")
	fmt.Printf("  Helper       : latlongrid, utmgrid\n")
	fmt.Printf("  Helper       : latlon2utm, utm2latlon\n")
	fmt.Printf("  Helper       : bearingline, latlonline, utmline\n")
	fmt.Printf("  Helper       : runlua\n")
	fmt.Printf("\nRemarks:\n")
	fmt.Printf("  create       : creates the meta data for a new map\n")
	fmt.Printf("  update       : updates the meta data of an existing map\n")
	fmt.Printf("  upload       : uploads a list of user supplied files\n")
	fmt.Printf("  order        : places a map build order\n")
	fmt.Printf("  state        : fetches the current state of the map\n")
	fmt.Printf("  download     : downloads a successful build map\n")
	fmt.Printf("  data         : fetches the current meta data of the map\n")
	fmt.Printf("  delete       : deletes all artifacts (files) of the map\n")
	fmt.Printf("  capabilities : fetches the capabilities of the map service\n")
	fmt.Printf("  unzip        : unzips the downloaded map file\n")
	fmt.Printf("  passepartout : calculates wkt passe-partout from base values\n")
	fmt.Printf("  rectangle    : calculates wkt rectangle from base values\n")
	fmt.Printf("  cropmarks    : calculates wkt crop marks from base values\n")
	fmt.Printf("  latlongrid   : creates lat/lon grid in geojson format\n")
	fmt.Printf("  utmgrid      : creates utm grid in geojson format\n")
	fmt.Printf("  latlon2utm   : converts coordinates from lat/lon to utm\n")
	fmt.Printf("  utm2latlon   : converts coordinates from utm to lat/lon\n")
	fmt.Printf("  bearingline  : creates geographic line in geojson format\n")
	fmt.Printf("  latlonline   : creates geographic line in geojson format\n")
	fmt.Printf("  utmline      : creates geographic line in geojson format\n")
	fmt.Printf("  runlua       : run lua 5.1 script for generating labels\n")
	fmt.Printf("\nFiles:\n")
	fmt.Printf("  %-13s: unique map identifier\n", mapIDFile)
	fmt.Printf("  %-13s: map definition parameters\n", mapDefinitionFile)
	fmt.Printf("\nHow to start:\n")
	fmt.Printf("  - Download and unzip the 'template' map from 'printmaps-osm.de'.\n")
	fmt.Printf("  - Build the 'template' map by running the actions:\n")
	fmt.Printf("    'create', 'upload', 'order', 'state', 'download', 'unzip'\n")
	fmt.Printf("  - View the map with an appropriate application.\n")
	fmt.Printf("  - Modify the map definition file '%s' to your needs.\n", mapDefinitionFile)
	fmt.Printf("\n")
	os.Exit(1)
}
func create() {
	if mapID != "" {
		fmt.Printf("\nnothing to do ... '%s' already exists\n", mapIDFile)
		fmt.Printf("use '%s update' to update '%s'\n", progName, mapDefinitionFile)
		return
	}
	pmData := pd.PrintmapsData{}
	pmData.Data.Type = "maps"
	pmData.Data.ID = mapID
	pmData.Data.Attributes = mapConfig.Metadata
	requestURL := mapConfig.ServiceURL + "metadata"
	data, err := json.MarshalIndent(pmData, pd.IndentPrefix, pd.IndexString)
	if err != nil {
		log.Fatalf("error <%v> at json.MarshalIndent()", err)
	}
	req, err := http.NewRequest("POST", requestURL, bytes.NewReader(data))
	if err != nil {
		log.Fatalf("error <%v> at http.NewRequest()", err)
	}
	req.Header.Add("Content-Type", "application/vnd.api+json; charset=utf-8")
	req.Header.Add("Accept", "application/vnd.api+json; charset=utf-8")
	printRequest(req, true)
	resp, err := netClient.Do(req)
	if err != nil {
		log.Fatalf("error <%v> at http.Do()", err)
	}
	defer resp.Body.Close()
	printResponse(resp, true)
	printSuccess(resp, http.StatusCreated)
	data, err = ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Fatalf("error <%v> at ioutil.ReadAll()", err)
	}
	pmDataResponse := pd.PrintmapsData{}
	err = json.Unmarshal(data, &pmDataResponse)
	if err != nil {
		log.Fatalf("error <%v> at json.Unmarshal()", err)
	}
	err = ioutil.WriteFile(mapIDFile, []byte(pmDataResponse.Data.ID), 0666)
	if err != nil {
		log.Fatalf("error <%v> at ioutil.WriteFile()", err)
	}
}
func update() {
	pmData := pd.PrintmapsData{}
	pmData.Data.Type = "maps"
	pmData.Data.ID = mapID
	pmData.Data.Attributes = mapConfig.Metadata
	requestURL := mapConfig.ServiceURL + "metadata"
	data, err := json.MarshalIndent(pmData, pd.IndentPrefix, pd.IndexString)
	if err != nil {
		log.Fatalf("error <%v> at json.MarshalIndent()", err)
	}
	req, err := http.NewRequest("PATCH", requestURL, bytes.NewReader(data))
	if err != nil {
		log.Fatalf("error <%v> at http.NewRequest()", err)
	}
	req.Header.Add("Content-Type", "application/vnd.api+json; charset=utf-8")
	req.Header.Add("Accept", "application/vnd.api+json; charset=utf-8")
	printRequest(req, true)
	resp, err := netClient.Do(req)
	if err != nil {
		log.Fatalf("error <%v> at http.Do()", err)
	}
	defer resp.Body.Close()
	printResponse(resp, true)
	printSuccess(resp, http.StatusOK)
}
func upload(filename string) {
	requestURL := mapConfig.ServiceURL + "upload/" + mapID
	bodyBuf := &bytes.Buffer{}
	bodyWriter := multipart.NewWriter(bodyBuf)
	_, destinationFilename := filepath.Split(filename)
	fileWriter, err := bodyWriter.CreateFormFile("file", destinationFilename)
	if err != nil {
		log.Fatalf("error <%v> at CreateFormFile()", err)
	}
	fh, err := os.Open(filename)
	if err != nil {
		log.Fatalf("error <%v> at os.Open(), file = %s", err, filename)
	}
	_, err = io.Copy(fileWriter, fh)
	if err != nil {
		log.Fatalf("error <%v> at io.Copy()", err)
	}
	bodyWriter.Close()
	req, err := http.NewRequest("POST", requestURL, bodyBuf)
	if err != nil {
		log.Fatalf("error <%v> at http.NewRequest()", err)
	}
	req.Header.Add("Accept", "application/vnd.api+json; charset=utf-8")
	req.Header.Set("Content-Type", bodyWriter.FormDataContentType())
	printRequest(req, false)
	resp, err := netClient.Do(req)
	if err != nil {
		log.Fatalf("error <%v> at http.Do()", err)
	}
	defer resp.Body.Close()
	printResponse(resp, true)
	printSuccess(resp, http.StatusCreated)
}