package main

import (
	"errors"
	"io"
	"local/encoder"
	"os"
	"strconv"
)

func key() []byte {
	k := []byte(os.Getenv("KEY"))
	if len(k) == 0 {
		panic("KEY is empty")
	}
	return k
}

func do_stdin_op(op string, src ...io.Reader) (io.Reader, error) {
	k := key()
	bops := []encoder.BOP{
		&encoder.Salter{},
		//&encoder.Zipper{},
		&encoder.AES{Key: k},
		//&encoder.Zipper{},
		//&encoder.PAR2{},
	}
	if os.Getenv("chunksize") == "" {
		os.Setenv("chunksize", "1")
	}
	chunksize, err := strconv.ParseFloat(os.Getenv("chunksize"), 64)
	if err != nil {
		return nil, err
	}
	//encoder.SetPipeBuffSize(int(chunksize * 1000 * 1000 * 1000 / float64(len(bops)+1) * .66))
	encoder.SetPipeBuffSize(int(chunksize * 1000 * 1000 * 1000 * .9))
	enc, err := encoder.New(nil, bops...)
	if err != nil {
		return nil, err
	}
	var o io.Reader = os.Stdin
	if len(src) > 0 {
		o = src[0]
	}
	var p io.Reader
	switch op {
	case "enc":
		p, err = enc.Encode2(o)
	case "dec":
		p, err = enc.Decode2(o)
	default:
		err = errors.New("unknown op " + op)
	}
	return p, err
}

func DecIO(src io.Reader) (io.Reader, error) {
	return do_stdin_op("dec", src)
}

func EncIO(src io.Reader) (io.Reader, error) {
	return do_stdin_op("enc", src)
}

func Enc(src ...io.Reader) error {
	b, err := do_stdin_op("enc", src...)
	if err == nil {
		if _, err := io.Copy(os.Stdout, b); err != nil {
			return err
		}
	}
	return err
}

func Dec(src ...io.Reader) error {
	b, err := do_stdin_op("dec", src...)
	if err == nil {
		if _, err = io.Copy(os.Stdout, b); err != nil {
			return err
		}
	}
	return err
}
