// zig fmt: off
const std = @import("std");
const Store = @import("../store.zig");
const json_utils = @import("../json_utils.zig");
const DropRate = @import("./drop_rate.zig");
const EnumStringUtils = @import("../enum_string_utils.zig").EnumStringUtils;

const Resource = @This();

pub const Skill = enum {
    mining,
    woodcutting,
    fishing,
    alchemy,

    const Utils = EnumStringUtils(Skill, .{
        .{ "mining"     , Skill.mining      },
        .{ "woodcutting", Skill.woodcutting },
        .{ "fishing"    , Skill.fishing     },
        .{ "alchemy"    , Skill.alchemy     },
    });

    pub const toString = Utils.toString;
    pub const fromString = Utils.fromString;
};

pub const Name = std.BoundedArray(u8, 32);

pub const max_code_size = 32;
pub const Code = std.BoundedArray(u8, max_code_size);

pub const Drops = std.BoundedArray(DropRate, 16);

name: Name,
code: Code,
skill: Skill,
level: u64,
drops: Drops,

pub fn parse(store: *Store, obj: std.json.ObjectMap) !Resource {
    const name = try json_utils.getStringRequired(obj, "name");
    const code = try json_utils.getStringRequired(obj, "code");
    const level = try json_utils.getPositiveIntegerRequired(obj, "level");
    const skill = try json_utils.getStringRequired(obj, "skill");

    const drops_array = try json_utils.getArrayRequired(obj, "drops");
    var drops = Drops.init(0) catch unreachable;
    drops.len = @intCast(try DropRate.parseDrops(store, drops_array, &drops.buffer));

    return Resource{
        .name = try Name.fromSlice(name),
        .code = try Code.fromSlice(code),
        .level = level,
        .skill = Skill.fromString(skill) orelse return error.InvalidSkill,
        .drops = drops
    };
}

pub fn parseAndAppend(store: *Store, obj: std.json.ObjectMap) !Store.Id {
    return store.resources.appendOrUpdate(try parse(store, obj));
}
