package ui

import "../shared"

Job_Type :: enum {
	Generate_Script,
	Generate_Character,
	Generate_Panel,
	Export,
}

Job_Status :: enum {
	Queued,
	Running,
	Completed,
	Failed,
	Cancelled,
}

Background_Job :: struct {
	id: int,
	type: Job_Type,
	status: Job_Status,
	message: string,
	progress: f32,
	cancel_requested: bool,
}

Job_Manager :: struct {
	next_id: int,
	jobs: [dynamic]Background_Job,
}

new_job_manager :: proc() -> Job_Manager {
	return Job_Manager{next_id = 1}
}

submit_job :: proc(m: ^Job_Manager, t: Job_Type, message: string) -> int {
	id := m.next_id
	m.next_id += 1
	append(&m.jobs, Background_Job{id = id, type = t, status = .Queued, message = message})
	return id
}

job_index_by_id :: proc(m: ^Job_Manager, id: int) -> int {
	for j, i in m.jobs {
		if j.id == id {
			return i
		}
	}
	return -1
}

mark_job_running :: proc(m: ^Job_Manager, id: int) -> shared.App_Error {
	idx := job_index_by_id(m, id)
	if idx < 0 {
		return shared.new_error(.Generation, "job not found", true)
	}
	m.jobs[idx].status = .Running
	return shared.ok()
}

mark_job_completed :: proc(m: ^Job_Manager, id: int) -> shared.App_Error {
	idx := job_index_by_id(m, id)
	if idx < 0 {
		return shared.new_error(.Generation, "job not found", true)
	}
	if m.jobs[idx].cancel_requested {
		m.jobs[idx].status = .Cancelled
	} else {
		m.jobs[idx].status = .Completed
	}
	return shared.ok()
}

mark_job_failed :: proc(m: ^Job_Manager, id: int, message: string) -> shared.App_Error {
	idx := job_index_by_id(m, id)
	if idx < 0 {
		return shared.new_error(.Generation, "job not found", true)
	}
	m.jobs[idx].status = .Failed
	m.jobs[idx].message = message
	return shared.ok()
}

request_job_cancel :: proc(m: ^Job_Manager, id: int) -> shared.App_Error {
	idx := job_index_by_id(m, id)
	if idx < 0 {
		return shared.new_error(.Generation, "job not found", true)
	}
	m.jobs[idx].cancel_requested = true
	if m.jobs[idx].status != .Completed && m.jobs[idx].status != .Failed {
		m.jobs[idx].status = .Cancelled
	}
	return shared.ok()
}

active_jobs_count :: proc(m: Job_Manager) -> int {
	count := 0
	for j in m.jobs {
		if j.status == .Queued || j.status == .Running {
			count += 1
		}
	}
	return count
}

update_job_progress :: proc(m: ^Job_Manager, id: int, progress: f32) -> shared.App_Error {
	idx := job_index_by_id(m, id)
	if idx < 0 {
		return shared.new_error(.Generation, "job not found", true)
	}
	m.jobs[idx].progress = progress
	return shared.ok()
}
