package lightning

import (
	"bufio"
	"bytes"
	"flag"
	"fmt"
	"io"
	"os"

	"github.com/arvados/lightning/hgvs"
)

type diffFasta struct{}

func (cmd *diffFasta) RunCommand(prog string, args []string, stdin io.Reader, stdout, stderr io.Writer) int {
	var err error
	defer func() {
		if err != nil {
			fmt.Fprintf(stderr, "%s\n", err)
		}
	}()
	flags := flag.NewFlagSet("", flag.ContinueOnError)
	flags.SetOutput(stderr)
	offset := flags.Int("offset", 0, "coordinate offset")
	sequence := flags.String("sequence", "chr1", "sequence label")
	timeout := flags.Duration("timeout", 0, "timeout (examples: \"1s\", \"1ms\")")
	err = flags.Parse(args)
	if err == flag.ErrHelp {
		err = nil
		return 0
	} else if err != nil {
		return 2
	}
	if len(flags.Args()) != 2 {
		err = fmt.Errorf("usage: %s [options] a.fasta b.fasta", prog)
		return 2
	}

	var fasta [2][]byte
	errs := make(chan error, 2)
	for idx, fnm := range flags.Args() {
		idx, fnm := idx, fnm
		go func() {
			f, err := os.Open(fnm)
			if err != nil {
				errs <- err
				return
			}
			defer f.Close()
			scanner := bufio.NewScanner(f)
			scanner.Buffer(nil, 64*1024*1024)
			for scanner.Scan() {
				buf := scanner.Bytes()
				if len(buf) > 0 && buf[0] != '>' {
					fasta[idx] = append(fasta[idx], bytes.ToUpper(buf)...)
				}
			}
			errs <- scanner.Err()
		}()
	}
	for range flags.Args() {
		if err = <-errs; err != nil {
			return 1
		}
	}

	variants, timedOut := hgvs.Diff(string(fasta[0]), string(fasta[1]), *timeout)
	if *offset != 0 {
		for i := range variants {
			variants[i].Position += *offset
		}
	}
	for _, v := range variants {
		fmt.Fprintf(stdout, "%s:g.%s\t%s\t%d\t%s\t%s\t%v\n", *sequence, v.String(), *sequence, v.Position, v.Ref, v.New, timedOut)
	}
	return 0
}