package models

import (
	"errors"
	"fmt"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
)

type Service struct {
	Name             string    `json:"name"`
	Description      string    `json:"description"`
	ExecutablePath   string    `json:"executablePath,omitempty"`
	WorkingDirectory string    `json:"workingDirectory,omitempty"`
	Arguments        []string  `json:"arguments,omitempty"`
	State            string    `json:"-"`
	Cmd              *exec.Cmd `json:"-"`
	Stopping         bool      `json:"-"`
}

func (s *Service) Start(errFunc func(e string)) error {
	s.State = "Error"
	absolutePath, err := filepath.Abs(s.ExecutablePath)
	if err != nil {
		return err
	}

	var arguments []string

	for _, a := range s.Arguments {
		arguments = append(arguments, strings.Split(a, " ")...)
	}
	s.Cmd = exec.Command(absolutePath, arguments...)
	s.Cmd.Dir = s.WorkingDirectory
	s.Cmd.Stdout = os.Stdout
	s.Cmd.Stderr = os.Stderr

	err = s.Cmd.Start()
	if err != nil {
		return err
	}

	go func() {
		err := s.Cmd.Wait()
		if err != nil {
			// Process exited with error
			if exitErr, ok := err.(*exec.ExitError); ok {
				if !s.Stopping {
					errFunc(fmt.Sprintf("Command failed with exit code %d: %v", exitErr.ExitCode(), err))
				}
			} else {
				errFunc(fmt.Sprintf("Command wait error: %v", err))
			}
		}
		s.Stopping = false
	}()

	s.State = "Running"
	return nil
}

func (s *Service) Stop() error {
	s.State = "Error"

	if s.Cmd == nil {
		return errors.New("process nil pointer")
	}

	// Stop (kill) the process
	s.Stopping = true
	err := s.Cmd.Process.Kill()
	if err != nil {
		return err
	}

	s.State = "Stopped"
	return nil
}
