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

const Artificer = @import("./artificer.zig");
const Context = Artificer.GoalContext;
const Requirements = Artificer.Requirements;

const Goal = @This();

item: Api.Store.Id,
quantity: u64,

fn getCraftMultiples(self: Goal, craft: Api.Craft) u64 {
    return @intFromFloat(@ceil(
        @as(f32, @floatFromInt(self.quantity)) /
        @as(f32, @floatFromInt(craft.quantity))
    ));
}

pub fn tick(self: *Goal, ctx: *Context) !void {
    const store = ctx.store;

    if (self.quantity == 0) {
        ctx.completed = true;
        return;
    }

    const item = store.items.get(self.item).?;
    const craft = item.craft.?;

    const skill = craft.skill.toCharacterSkill();
    if (ctx.character.skills.get(skill).level < craft.level) {
        return error.SkillTooLow;
    }

    const workshop_position = ctx.findNearestWorkstation(craft.skill).?;
    if (!workshop_position.eql(ctx.character.position)) {
        ctx.queueAction(.{
            .move = workshop_position
        });
        return;
    }

    ctx.queueAction(.{
        .craft = .{ .item = self.item, .quantity = self.quantity }
    });
}

pub fn requirements(self: Goal, ctx: *Context) Requirements {
    var reqs: Requirements = .{};

    const store = ctx.store;
    const item = store.items.get(self.item).?;
    const craft = item.craft.?;
    const craft_multiples = self.getCraftMultiples(craft);

    for (craft.items.slice()) |craft_item| {
        reqs.items.addAssumeCapacity(craft_item.id, craft_item.quantity * craft_multiples);
    }

    return reqs;
}

pub fn onActionCompleted(self: *Goal, ctx: *Context, result: Artificer.ActionResult) void {
    _ = ctx;

    if (result == .craft) {
        const craft_result = result.craft;
        const craft_quantity = craft_result.details.items.getQuantity(self.item);

        if (self.quantity > craft_quantity) {
            self.quantity -= craft_quantity;
        } else {
            self.quantity = 0;
        }
    }
}
