const std = @import("std");

const Piece = @import("piece.zig");

const Self = @This();

contents: [14]?Piece.Type,
prng: std.rand.DefaultPrng,

pub fn init() Self {
    var ret = Self{
        .contents = undefined,
        .prng = std.rand.DefaultPrng.init(@intCast(u64, std.time.milliTimestamp())),
    };
    // We must fill all of the array
    for (ret.contents[0..7]) |_, i| {
        ret.contents[i] = @intToEnum(Piece.Type, i);
    }
    // Then we shuffle
    ret.prng.random().shuffle(?Piece.Type, ret.contents[0..7]);

    for (ret.contents[7..14]) |_, i| {
        ret.contents[i + 7] = @intToEnum(Piece.Type, i);
    }
    // Then we shuffle
    ret.updateSeed();
    ret.prng.random().shuffle(?Piece.Type, ret.contents[7..14]);

    return ret;
}

pub fn pop(self: *Self) Piece {
    var ret_type = Piece.Type.i; // TODO Throw Error when no piece found
    if (self.contents[0]) |head| {
        ret_type = head;
        // Reorganize the bag
        for (self.contents) |_, i| {
            if (i + 1 >= self.contents.len) {
                break;
            }
            if (self.contents[i + 1]) |next| {
                self.contents[i] = next;
                self.contents[i + 1] = null;
            } else break;
        }
        // Get more pieces if needed
        if (self.contents[7] == null) {
            for (self.contents[7..14]) |_, i| {
                self.contents[i + 7] = @intToEnum(Piece.Type, i);
            }
            self.updateSeed();
            self.prng.random().shuffle(?Piece.Type, self.contents[7..14]);
        }
    }
    return Piece.init(ret_type);
}

fn updateSeed(self: *Self) void {
    self.prng.seed(@intCast(u64, std.time.milliTimestamp()));
}
