package gui

import "core:fmt"
import "core:os"
import "core:path/filepath"
import rl "vendor:raylib"
import "../ui"

build_diagnostics_snapshot :: proc(controller: ui.App_Controller, is_dirty, autosave_enabled, project_ok, export_ok: bool, autosave_secs: int, project_path, export_path: string, log_show_lines: i32, log_oldest_first: bool) -> string {
	log_order := "newest"
	if log_oldest_first {
		log_order = "oldest"
	}
	return fmt.aprintf("screen=%s workflow=%v next=%s dirty=%s autosave=%s(%ds) content=pages:%d,panels:%d,layouts:%d,chars:%d paths=P:%s,E:%s project=%s export=%s log=%d,%s uptime=%.1fs", ui.screen_name(controller.active_screen), controller.state.workflow.current_step, gui_next_hint(controller), yn(is_dirty), yn(autosave_enabled), autosave_secs, len(controller.state.script.pages), len(controller.state.panel_images), len(controller.state.page_layouts), len(controller.state.characters), yn(project_ok), yn(export_ok), project_path, export_path, log_show_lines, log_order, rl.GetTime())
}

build_action_log_snapshot :: proc(log: Action_Log) -> string {
	if log.count == 0 {
		return fmt.aprintf("(action log empty)")
	}
	now := rl.GetTime()
	max_lines := len(log.entries)
	if log.count < max_lines {
		max_lines = log.count
	}
	out := ""
	for line in 0..<max_lines {
		idx := (log.count - 1 - line) % len(log.entries)
		if idx < 0 {
			idx += len(log.entries)
		}
		entry := fmt.aprintf("[%2.0fs] %s", now-log.entry_times[idx], log.entries[idx])
		if line == 0 {
			out = entry
		} else {
			prev := out
			out = fmt.aprintf("%s\n%s", prev, entry)
			delete(prev)
			delete(entry)
		}
	}
	return out
}

build_session_report :: proc(controller: ui.App_Controller, log: Action_Log, is_dirty, autosave_enabled, project_ok, export_ok: bool, autosave_secs: int, project_path, export_path: string, log_show_lines: i32, log_oldest_first: bool) -> string {
	diag := build_diagnostics_snapshot(controller, is_dirty, autosave_enabled, project_ok, export_ok, autosave_secs, project_path, export_path, log_show_lines, log_oldest_first)
	log_text := build_action_log_snapshot(log)
	report := fmt.aprintf("# comic-odin gui session report\n\n[meta]\ngenerated_uptime=%.1fs\n\n[diagnostics]\n%s\n\n[action_log]\n%s\n", rl.GetTime(), diag, log_text)
	delete(diag)
	delete(log_text)
	return report
}

Diagnostics_Action_Context :: struct {
	controller:       ^ui.App_Controller,
	action_log:       ^Action_Log,
	is_dirty:         bool,
	autosave_enabled: bool,
	project_ok:       bool,
	export_ok:        bool,
	autosave_secs:    int,
	project_path:     string,
	export_path:      string,
	log_show_lines:   i32,
	log_oldest_first: bool,
}

make_diagnostics_action_context :: proc(controller: ^ui.App_Controller, action_log: ^Action_Log, is_dirty, autosave_enabled, project_ok, export_ok: bool, autosave_secs: int, project_path, export_path: string, log_show_lines: i32, log_oldest_first: bool) -> Diagnostics_Action_Context {
	return Diagnostics_Action_Context{
		controller = controller,
		action_log = action_log,
		is_dirty = is_dirty,
		autosave_enabled = autosave_enabled,
		project_ok = project_ok,
		export_ok = export_ok,
		autosave_secs = autosave_secs,
		project_path = project_path,
		export_path = export_path,
		log_show_lines = log_show_lines,
		log_oldest_first = log_oldest_first,
	}
}

diagnostics_path_for_project :: proc(project_path: string) -> string {
	dir, _ := filepath.split(project_path)
	if len(dir) == 0 {
		dir = "./"
	}
	parts := []string{dir, "gui_diagnostics.txt"}
	joined, err := filepath.join(parts)
	if err != nil {
		return "./gui_diagnostics.txt"
	}
	return joined
}

session_report_path_for_project :: proc(project_path: string) -> string {
	dir, _ := filepath.split(project_path)
	if len(dir) == 0 {
		dir = "./"
	}
	parts := []string{dir, "gui_session_report.txt"}
	joined, err := filepath.join(parts)
	if err != nil {
		return "./gui_session_report.txt"
	}
	return joined
}

write_diagnostics_file :: proc(project_path, diag: string) -> string {
	diag_path := diagnostics_path_for_project(project_path)
	defer delete(diag_path)
	if err := os.write_entire_file(diag_path, diag); err == nil {
		return fmt.aprintf("Wrote diagnostics file: %s", diag_path)
	}
	return fmt.aprintf("Failed writing diagnostics file")
}

write_session_report_file :: proc(project_path, report: string) -> string {
	report_path := session_report_path_for_project(project_path)
	defer delete(report_path)
	if err := os.write_entire_file(report_path, report); err == nil {
		return fmt.aprintf("Wrote session report: %s", report_path)
	}
	return fmt.aprintf("Failed writing session report")
}

write_session_report_with_message :: proc(ctx: Diagnostics_Action_Context) -> string {
	report := build_session_report(ctx.controller^, ctx.action_log^, ctx.is_dirty, ctx.autosave_enabled, ctx.project_ok, ctx.export_ok, ctx.autosave_secs, ctx.project_path, ctx.export_path, ctx.log_show_lines, ctx.log_oldest_first)
	msg := write_session_report_file(ctx.project_path, report)
	delete(report)
	return msg
}

write_diagnostics_with_message :: proc(ctx: Diagnostics_Action_Context) -> string {
	diag := build_diagnostics_snapshot(ctx.controller^, ctx.is_dirty, ctx.autosave_enabled, ctx.project_ok, ctx.export_ok, ctx.autosave_secs, ctx.project_path, ctx.export_path, ctx.log_show_lines, ctx.log_oldest_first)
	msg := write_diagnostics_file(ctx.project_path, diag)
	delete(diag)
	return msg
}

copy_diagnostics_with_message :: proc(ctx: Diagnostics_Action_Context) -> string {
	diag := build_diagnostics_snapshot(ctx.controller^, ctx.is_dirty, ctx.autosave_enabled, ctx.project_ok, ctx.export_ok, ctx.autosave_secs, ctx.project_path, ctx.export_path, ctx.log_show_lines, ctx.log_oldest_first)
	msg := copy_text_with_status(diag, "Copied diagnostics snapshot")
	delete(diag)
	return msg
}

copy_action_log_snapshot_with_message :: proc(ctx: Diagnostics_Action_Context) -> string {
	log_text := build_action_log_snapshot(ctx.action_log^)
	msg := copy_text_with_status(log_text, "Copied action log snapshot")
	delete(log_text)
	return msg
}

copy_text_with_status :: proc(text, status: string) -> string {
	rl.SetClipboardText(fmt.ctprintf("%s", text))
	return status
}
