// zig fmt: off
const std = @import("std");
const Api = @import("artifacts-api");
const Allocator = std.mem.Allocator;

pub const Brain = @import("./brain.zig");
pub const TaskGraph = @import("./task_graph.zig");

const Artificer = @This();

const expiration_margin: u64 = 100 * std.time.ns_per_ms; // 100ms
const server_down_retry_interval = 5; // minutes

server: *Api.Server,
// characters: std.ArrayList(Brain),
// task_graph: TaskGraph,

// paused_until: ?i64 = null, // ms

pub fn init(allocator: Allocator, server: *Api.Server) !Artificer {
    // var characters = std.ArrayList(Brain).init(allocator);
    // errdefer characters.deinit(); // TODO: Add character deinit
    //
    // const chars = try server.listMyCharacters();
    // defer chars.deinit();
    //
    // for (chars.items) |char| {
    //     try characters.append(try Brain.init(allocator, char.name));
    // }

    _ = allocator;
    return Artificer{
        .server = server,
        // .characters = characters,
        // .task_graph = TaskGraph.init(allocator),
    };
}

pub fn deinit(self: *Artificer) void {
    _ = self;
    // for (self.characters.items) |brain| {
    //     brain.deinit();
    // }
    // self.characters.deinit();
    // self.server.deinit();
}

pub fn tick(self: *Artificer) !void {
    _ = self;
}

// pub fn step(self: *Artificer) !void {
//     if (self.paused_until) |paused_until| {
//         if (std.time.milliTimestamp() < paused_until) {
//             return;
//         }
//         self.paused_until = null;
//     }
//
//     runNextActions(self.characters.items, &self.server) catch |err| switch (err) {
//         Api.FetchError.ServerUnavailable => {
//             self.paused_until = std.time.milliTimestamp() + std.time.ms_per_min * server_down_retry_interval;
//             std.log.warn("Server is down, retrying in {}min", .{server_down_retry_interval});
//             return;
//         },
//         else => return err,
//     };
//
//     for (self.characters.items) |*brain| {
//         if (brain.task != null) {
//             try brain.step(&self.server);
//             continue;
//         }
//
//         const character = self.server.store.getCharacter(brain.name).?;
//         if (character.task) |taskmaster_task| {
//             if (taskmaster_task.total > taskmaster_task.progress) {
//                 switch (taskmaster_task.type) {
//                     .monsters => {
//                         const monster_code = self.server.store.getCode(taskmaster_task.target_id).?;
//
//                         const maps = try self.server.getMaps(.{ .code = monster_code });
//                         defer maps.deinit();
//
//                         if (maps.items.len > 0) {
//                             const resource_map: Api.Map = maps.items[0];
//                             std.debug.print("fight at {}\n", .{resource_map.position});
//
//                             brain.task = .{ .fight = .{
//                                 .at = resource_map.position,
//                                 .until = .{ .quantity = taskmaster_task.total - taskmaster_task.progress },
//                             } };
//                         }
//                     },
//                     .crafts => {},
//                     .resources => {},
//                 }
//             }
//         } else {
//             brain.task = .{ .accept_task = .{} };
//         }
//     }
// }
//
// pub fn nextStepAt(self: *Artificer) i64 {
//     if (self.paused_until) |paused_until| {
//         return paused_until;
//     }
//
//     return earliestCooldown(self.characters.items, &self.server) orelse 0;
// }
//
// fn earliestCooldown(characters: []Brain, api: *Api.Server) ?i64 {
//     var earliest_cooldown: ?i64 = null;
//     for (characters) |*brain| {
//         if (brain.action_queue.items.len == 0) continue;
//
//         const cooldown = brain.cooldown(api);
//         if (earliest_cooldown == null or earliest_cooldown.? > cooldown) {
//             earliest_cooldown = cooldown;
//         }
//     }
//
//     return earliest_cooldown;
// }
//
// fn runNextActions(characters: []Brain, api: *Api.Server) !void {
//     for (characters) |*brain| {
//         if (brain.action_queue.items.len == 0) continue;
//
//         const cooldown = brain.cooldown(api);
//         if (std.time.milliTimestamp() >= cooldown) {
//             try brain.performNextAction(api);
//         }
//     }
// }
