package main

import (
	"flag"
	"fmt"
	"io"
	"log"
	"os"
	"time"

	"golang.org/x/text/encoding/simplifiedchinese"
	"golang.org/x/text/transform"
)

func main() {
	// TODO: support more character set.
	fromPtr := flag.String("f", "gbk", "encoding of original text, support gbk(gb18030, gb2312) and utf8")
	toPtr := flag.String("t", "utf8", "encoding for output, support gbk(gb18030, gb2312) and utf8")
	inputPtr := flag.String("i", "", "input file")
	outputPtr := flag.String("o", "", "output file")

	flag.Parse()

	// open input file
	fi, err := os.Open(*inputPtr)
	if err != nil {
		panic(err)
	}
	// close fi on exit and check for its returned error
	defer func() {
		if err := fi.Close(); err != nil {
			panic(err)
		}
	}()

	var reader *transform.Reader
	if *fromPtr == "utf8" {
		switch *toPtr {
		case "gb2312":
			reader = transform.NewReader(fi, simplifiedchinese.HZGB2312.NewEncoder())
		case "gbk":
			reader = transform.NewReader(fi, simplifiedchinese.GBK.NewEncoder())
		case "gb18030":
			reader = transform.NewReader(fi, simplifiedchinese.GB18030.NewEncoder())
		default:
			panic(fmt.Sprintf("converting from %s to %s is not supported", *fromPtr, *toPtr))
		}
	} else if *toPtr == "utf8" {
		switch *fromPtr {
		case "gb2312":
			reader = transform.NewReader(fi, simplifiedchinese.HZGB2312.NewDecoder())
		case "gbk":
			reader = transform.NewReader(fi, simplifiedchinese.GBK.NewDecoder())
		case "gb18030":
			reader = transform.NewReader(fi, simplifiedchinese.GB18030.NewDecoder())
		default:
			panic(fmt.Sprintf("converting from %s to %s is not supported", *fromPtr, *toPtr))
		}
	} else {
		panic(fmt.Sprintf("converting from %s to %s is not supported", *fromPtr, *toPtr))
	}

	// open output file
	fo, err := os.Create(*outputPtr)
	if err != nil {
		panic(err)
	}
	// close fo on exit and check for its returned error
	defer func() {
		if err := fo.Close(); err != nil {
			panic(err)
		}
	}()

	// make a buffer to keep chunks that are read
	log.Printf("start converting %s to %s from %s to %s", *inputPtr, *outputPtr, *fromPtr, *toPtr)
	start := time.Now()
	buf := make([]byte, 1024)

	_, err = io.CopyBuffer(fo, reader, buf)
	if err != nil {
		panic(err)
	}
	log.Printf("convert finished, cost: %s", time.Since(start))
}
