const std = @import("std");
const print = std.debug.print;

pub fn main() !void
{
    const allocator = std.heap.page_allocator;
    var rules = std.ArrayList([]u8).init(allocator);
    var data = std.ArrayList([]u8).init(allocator);

    print("typeof arraylist: {}",.{@TypeOf(rules)});
    try readFile(allocator,"day5.txt",&rules,&data);    

    print("rules:\n",.{});
    for(rules.items) | rule |
    {
        print("{s}\n",.{rule});
    }
    print("data:\n",.{});
    for(data.items) | dat |
    {
        print("{s}\n",.{dat});
    }

    const values = try parseIntsToSlice(allocator,data.items[2]);
    print("ints: {d}\n",.{values.*});

    _ = try checkOrder(allocator,data.items[1],&rules);

}

fn readFile(allocator : std.mem.Allocator, filename : [] const u8, rules : *std.ArrayList([]u8), data : *std.ArrayList([]u8)) !void
{
    const file = try std.fs.cwd().openFile(filename,.{});
    var buf_reader = std.io.bufferedReader(file.reader());
    var reader = buf_reader.reader();

    var buf: [1024]u8 = undefined;

    while(try reader.readUntilDelimiterOrEof(&buf,'\n') )| line |
    {

            if(std.mem.indexOf(u8,line,"|")) | _ |
            {
                print("this is a rule: ",.{});
                try rules.append(try std.fmt.allocPrint(allocator,"{s}",.{line}));
            }
            else
            {
                try data.append( try std.fmt.allocPrint(allocator,"{s}",.{line}));
                print("this is a data set: ",.{});
            }

        print("{s}\n",.{line});
    }
}

fn parseIntsToSlice(allocator : std.mem.Allocator, data : []u8) !*[]u64
{
    var values : []u64 = try allocator.alloc(u64,0);
    var start_pos : usize = 0;

    //first must be different as dataset does not beginn with a ,
    
    if(std.mem.indexOfAnyPos(u8,data,0,",")) | index |
    {
        values = try allocator.realloc(values,values.len + 1);
        const cur_index = values.len - 1;
        
        //parses the string from beginning to , to an integer
        values[cur_index] = try std.fmt.parseInt(u64,data[0..index],10);
    }

    while(std.mem.indexOfAnyPos(u8,data,start_pos,",")) | index |  
    {
    if(start_pos >= data.len - 1) break;

        if(std.mem.indexOfAnyPos(u8,data,index+1,",")) | sub_index |
        {
            values = try allocator.realloc(values,values.len + 1);
            const cur_index = values.len - 1;
            
            //parses the string from , to , to an integer
            values[cur_index] = try std.fmt.parseInt(u64,data[index+1..sub_index],10);
            start_pos = sub_index;
        }
        else
        {
            values = try allocator.realloc(values,values.len + 1);
            const cur_index = values.len - 1;
            values[cur_index] = try std.fmt.parseInt(u64,data[index+1..data.len],10);
            break;
        }
    }
    return &values;
}
fn parseRule(allocator : std.mem.Allocator,rule : []u8) ![2]u64
{
    _ = allocator;

    if(std.mem.indexOf(u8,rule,"|")) | index |
    {
        const int1 = try std.fmt.parseInt(u64,rule[0..index],10);
        const int2 = try std.fmt.parseInt(u64,rule[index+1..],10);
        return .{int1,int2};
    }
    return.{0,0};
}

fn checkOrder(allocator : std.mem.Allocator,data : []u8,rules : *std.ArrayList([]u8)) !usize
{
    const nbrs = try parseIntsToSlice(allocator,data);
    //const nbrs2 = try parseIntsToSlice(allocator,data);
    var pass_test : bool = false;
    var fail_index : usize = 0;

    for(nbrs.*,0..) | nbr, index_nbr |
    {
        ruleFor : for (rules.items,0..) | rule, index_rule |
        {
            print("rule: {s}\n",.{rule});
            const rule_i = try parseRule(allocator,rule);
            if(nbr == rule_i[0])
            {
                print("apply rule: {d}\n",.{rule_i});
                print("nbrs2:{d}\n",.{nbrs});
                for(nbrs.*,0..) | nbr2, index_nbr2 |
                {
                    if(nbr2 == rule_i[1])
                    {
                        if(index_nbr2 > index_nbr)
                        {
                            pass_test = true;
                            break;
                        }
                        else
                        {
                            pass_test = false;
                            fail_index = index_rule;
                            break :ruleFor;
                        }
                    }
                }
                //else
                //{
                //    print("number not in rule\n",.{});
                //}
            }
        }
    }
    return 0;
}

