package cmd
import (
"encoding/json"
"fmt"
"os"
"strconv"
"strings"
"skraak/tools"
)
func printModifyUsage() {
fmt.Fprintf(os.Stderr, "Usage: skraak calls modify [options]\n\n")
fmt.Fprintf(os.Stderr, "Modify a label in a .data file.\n\n")
fmt.Fprintf(os.Stderr, "Options:\n")
fmt.Fprintf(os.Stderr, " --file <path> Path to .data file (required)\n")
fmt.Fprintf(os.Stderr, " --reviewer <name> Reviewer name (required)\n")
fmt.Fprintf(os.Stderr, " --filter <name> Filter name to match labels (required)\n")
fmt.Fprintf(os.Stderr, " --segment <start-end> Segment time range in integer seconds (required, e.g., 12-15)\n")
fmt.Fprintf(os.Stderr, " --certainty <int> Certainty value 0-100 (required)\n")
fmt.Fprintf(os.Stderr, " --species <name> Species to set (e.g., Kiwi, Kiwi+Male, Noise)\n")
fmt.Fprintf(os.Stderr, " --bookmark Mark segment as bookmarked for navigation\n")
fmt.Fprintf(os.Stderr, " --comment <text> User comment (max 140 chars, ASCII only)\n")
fmt.Fprintf(os.Stderr, "\nSegment matching:\n")
fmt.Fprintf(os.Stderr, " Segments are matched by floor(start) and ceil(end) times.\n")
fmt.Fprintf(os.Stderr, " For example, a segment from 12.3s to 14.5s matches --segment 12-15.\n")
fmt.Fprintf(os.Stderr, "\nBehavior:\n")
fmt.Fprintf(os.Stderr, " Always updates reviewer on file metadata.\n")
fmt.Fprintf(os.Stderr, " If all specified values match current values, no modification is made.\n")
fmt.Fprintf(os.Stderr, "\nExamples:\n")
fmt.Fprintf(os.Stderr, " # Change species and certainty (incorrect classification)\n")
fmt.Fprintf(os.Stderr, " skraak calls modify --file recording.data --reviewer GLM-5 \\\n")
fmt.Fprintf(os.Stderr, " --filter mymodel --segment 12-15 --species Kiwi+Male --certainty 100\n\n")
fmt.Fprintf(os.Stderr, " # Change certainty only (correct classification)\n")
fmt.Fprintf(os.Stderr, " skraak calls modify --file recording.data --reviewer GLM-5 \\\n")
fmt.Fprintf(os.Stderr, " --filter mymodel --segment 12-15 --certainty 100\n\n")
fmt.Fprintf(os.Stderr, " # Change to Noise (clears calltype)\n")
fmt.Fprintf(os.Stderr, " skraak calls modify --file recording.data --reviewer GLM-5 \\\n")
fmt.Fprintf(os.Stderr, " --filter mymodel --segment 67-88 --species Noise --certainty 100\n\n")
fmt.Fprintf(os.Stderr, " # Bookmark a segment for later review\n")
fmt.Fprintf(os.Stderr, " skraak calls modify --file recording.data --reviewer GLM-5 \\\n")
fmt.Fprintf(os.Stderr, " --filter mymodel --segment 12-15 --certainty 100 --bookmark\n\n")
fmt.Fprintf(os.Stderr, " # Add a comment to a segment\n")
fmt.Fprintf(os.Stderr, " skraak calls modify --file recording.data --reviewer GLM-5 \\\n")
fmt.Fprintf(os.Stderr, " --filter mymodel --segment 12-15 --certainty 100 --comment \"Good example of duet\"\n")
}
type modifyArgs struct {
file string
reviewer string
filter string
segment string
species string
comment string
certainty int
certaintySet bool
bookmark bool
}
func requireFlagValue(args []string, i int, flagName string) string {
if i+1 >= len(args) {
fmt.Fprintf(os.Stderr, "Error: %s requires a value\n", flagName)
os.Exit(1)
}
return args[i+1]
}
func parseModifyArgs(args []string) modifyArgs {
var ma modifyArgs
i := 0
for i < len(args) {
arg := args[i]
switch arg {
case "--file":
ma.file = requireFlagValue(args, i, "--file")
i += 2
case "--reviewer":
ma.reviewer = requireFlagValue(args, i, "--reviewer")
i += 2
case "--filter":
ma.filter = requireFlagValue(args, i, "--filter")
i += 2
case "--segment":
ma.segment = requireFlagValue(args, i, "--segment")
i += 2
case "--species":
ma.species = requireFlagValue(args, i, "--species")
i += 2
case "--certainty":
val := requireFlagValue(args, i, "--certainty")
v, err := strconv.Atoi(val)
if err != nil {
fmt.Fprintf(os.Stderr, "Error: --certainty must be an integer\n")
os.Exit(1)
}
ma.certainty = v
ma.certaintySet = true
i += 2
case "--bookmark":
ma.bookmark = true
i++
case "--comment":
ma.comment = requireFlagValue(args, i, "--comment")
i += 2
case "-h", "--help":
printModifyUsage()
os.Exit(0)
default:
if strings.HasPrefix(arg, "--") {
fmt.Fprintf(os.Stderr, "Error: unknown flag: %s\n\n", arg)
printModifyUsage()
os.Exit(1)
}
i++
}
}
return ma
}
func validateModifyArgs(ma modifyArgs) {
missing := []string{}
if ma.file == "" {
missing = append(missing, "--file")
}
if ma.reviewer == "" {
missing = append(missing, "--reviewer")
}
if ma.filter == "" {
missing = append(missing, "--filter")
}
if ma.segment == "" {
missing = append(missing, "--segment")
}
if !ma.certaintySet {
missing = append(missing, "--certainty")
}
if len(missing) > 0 {
fmt.Fprintf(os.Stderr, "Error: missing required flags: %v\n\n", missing)
printModifyUsage()
os.Exit(1)
}
if ma.certainty < 0 || ma.certainty > 100 {
fmt.Fprintf(os.Stderr, "Error: --certainty must be between 0 and 100\n")
os.Exit(1)
}
}
func RunCallsModify(args []string) {
ma := parseModifyArgs(args)
validateModifyArgs(ma)
input := tools.CallsModifyInput{
File: ma.file,
Reviewer: ma.reviewer,
Filter: ma.filter,
Segment: ma.segment,
Species: ma.species,
Certainty: ma.certainty,
Comment: ma.comment,
}
if ma.bookmark {
input.Bookmark = &ma.bookmark
}
result, err := tools.CallsModify(input)
if err != nil {
fmt.Fprintf(os.Stderr, "Error: %s\n", result.Error)
os.Exit(1)
}
data, _ := json.Marshal(result)
fmt.Println(string(data))
}