// For more tutorials: https://blog.learngoprogramming.com
//
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//

package main

import (
	"fmt"
	"os"
	"strings"
)

type recordFn func(record)

type iterator interface{ each(recordFn) error }
type digester interface{ digest(iterator) error }

type transform interface {
	digester
	iterator
}

type pipeline struct {
	src   iterator
	trans []transform
	dst   digester
}

func (p *pipeline) run() error {
	defer func() {
		n := p.src.(*logCount).count()
		fmt.Printf("%d records processed.\n", n)
	}()

	last := p.src

	for _, t := range p.trans {
		if err := t.digest(last); err != nil {
			return err
		}
		last = t
	}

	return p.dst.digest(last)
}

func newPipeline(src iterator, dst digester, t ...transform) *pipeline {
	return &pipeline{
		src:   &logCount{iterator: src},
		dst:   dst,
		trans: t,
	}
}

// fromFile generates a default report
func fromFile(path string) (*pipeline, error) {
	f, err := os.Open(path)
	if err != nil {
		return nil, err
	}

	var src iterator
	switch {
	case strings.HasSuffix(path, ".txt"):
		src = newTextLog(f)
	case strings.HasSuffix(path, ".jsonl"):
		src = newJSONLog(f)
	}

	return newPipeline(
		src,
		newTextReport(),
		groupBy(domainGrouper),
	), nil
}
