package main

import (
	"context"

	"git.cems.dev/cdricms/bdooc/proto"
	"github.com/wailsapp/wails/v2/pkg/runtime"
)

// App struct
type App struct {
	ctx       context.Context
	employees *proto.EmployeeList // Caching purposes
}

// NewApp creates a new App application struct
func NewApp() *App {
	return &App{}
}

// startup is called when the app starts. The context is saved
// so we can call the runtime methods
func (a *App) startup(ctx context.Context) {
	a.ctx = ctx
}

func (a *App) GetEmployees(path string, limit, page uint, column, query *string) ([]*proto.Employee, error) {
	if a.employees == nil {
		e, err := proto.LoadFromFile(path)
		if err != nil {
			return nil, err
		}
		a.employees = e
	}

	if column != nil && query != nil {
		e, err := a.employees.QueryEmployeesByColumn(proto.EmployeeField(proto.SnakeCaseToPascalCase(*column)), *query)
		if err != nil {
			return nil, err
		}
		if uint(len(e)) < page*limit+limit {
			return e[page*limit:], nil
		}
		return e[page*limit : page*limit+limit], nil
	}

	if uint(len(a.employees.Employees)) < page*limit+limit {
		return a.employees.Employees[page*limit:], nil
	}
	return a.employees.Employees[page*limit : page*limit+limit], nil
}

func (a *App) GetProtoPath() string {
	return a.OpenPath([]runtime.FileFilter{{
		DisplayName: "Proto binary file",
		Pattern:     "*.bin",
	}})
}

func (a *App) OpenPath(filters []runtime.FileFilter) string {
	path, err := runtime.OpenFileDialog(a.ctx, runtime.OpenDialogOptions{
		Filters: filters,
	})

	if err != nil {
		panic(err)
	}

	return path
}

type FunctionAgg string

const (
	AVG = FunctionAgg("AVG")
	SUM = FunctionAgg("SUM")
)

func (a *App) AggregateByColumn(groupBy proto.EmployeeField, on proto.EmployeeField, function FunctionAgg) map[string]float64 {
	return proto.AggregateByColumn(a.employees, proto.EmployeeField(proto.SnakeCaseToPascalCase(string(groupBy))), func(ep proto.EmployeePList) float64 {
		switch function {
		case AVG:
			return proto.Average(ep, proto.EmployeeField(proto.SnakeCaseToPascalCase(string(on))))
		case SUM:
			return proto.Sum(ep, proto.EmployeeField(proto.SnakeCaseToPascalCase(string(on))))
		}

		return 0.0
	})
}
