GetItemDifference(BlissHiveLogInventory before,
                          BlissHiveLogInventory after)
        {
            LinkedList <BlissHiveLogActivityItem> result = new LinkedList <BlissHiveLogActivityItem>();

            LinkedList <BlissHiveLogItem> beforeMerged = before.items;
            LinkedList <BlissHiveLogItem> afterMerged  = after.items;

            // Comparing items which were in the inventory, but aren't now
            //
            // For each item which was in the inventory before
            foreach (BlissHiveLogItem item in beforeMerged)
            {
                int count = 0;
                // For each item that was in the inventory after
                foreach (BlissHiveLogItem otherItem in afterMerged)
                {
                    // Can't compare inventory items to backpack items
                    if (item.location == otherItem.location)
                    {
                        // If the key is the same
                        if (otherItem.key == item.key)
                        {
                            // But the quantity was different ..
                            if (otherItem.quantity != item.quantity)
                            {
                                // Something changed, log it
                                result.AddLast(
                                    new BlissHiveLogActivityItem(otherItem.quantity - item.quantity, item,
                                                                 after.originalLogEntry.timestamp));
                            }
                            break;
                        }
                    }
                    // If the item apparantly wasn't in the new inventory
                    if (count == afterMerged.Count - 1)
                    {
                        // Log it
                        result.AddLast(
                            new BlissHiveLogActivityItem(-1, item,
                                                         after.originalLogEntry.timestamp));
                    }
                    // Increase the count
                    count++;
                }
            }

            // Comparing items that are now in the inventory,
            // but weren't there before
            //
            // For each item which was in the inventory after
            foreach (BlissHiveLogItem item in afterMerged)
            {
                int count = 0;
                // For each item that was in the inventory before
                foreach (BlissHiveLogItem otherItem in beforeMerged)
                {
                    // Can't compare inventory items to backpack items
                    if (item.location == otherItem.location)
                    {
                        // If the key is the same
                        if (otherItem.key == item.key)
                        {
                            // We already checked it above, skip it
                            break;
                        }
                    }
                    // If the item apparantly wasn't in the old inventory
                    if (count == beforeMerged.Count - 1)
                    {
                        // Log it
                        result.AddLast(
                            new BlissHiveLogActivityItem(1, item,
                                                         after.originalLogEntry.timestamp));
                    }
                    count++;
                }
            }


            return(result);
        }
        /// <summary>
        /// Gets the difference between two inventories.
        /// </summary>
        /// <param name="survivor"></param>
        /// <param name="before"></param>
        /// <param name="after"></param>
        /// <returns></returns>
        public static LinkedList<BlissHiveLogActivityItem> GetItemDifference(BlissHiveLogInventory before,
                              BlissHiveLogInventory after)
        {
            LinkedList<BlissHiveLogActivityItem> result = new LinkedList<BlissHiveLogActivityItem>();

            LinkedList<BlissHiveLogItem> beforeMerged = before.items;
            LinkedList<BlissHiveLogItem> afterMerged = after.items;

            // Comparing items which were in the inventory, but aren't now
            //
            // For each item which was in the inventory before
            foreach (BlissHiveLogItem item in beforeMerged) {
                int count = 0;
                // For each item that was in the inventory after
                foreach (BlissHiveLogItem otherItem in afterMerged) {
                    // Can't compare inventory items to backpack items
                    if (item.location == otherItem.location) {
                        // If the key is the same
                        if (otherItem.key == item.key) {
                            // But the quantity was different ..
                            if (otherItem.quantity != item.quantity) {
                                // Something changed, log it
                                result.AddLast(
                                    new BlissHiveLogActivityItem(otherItem.quantity - item.quantity, item,
                                            after.originalLogEntry.timestamp));
                            }
                            break;
                        }
                    }
                    // If the item apparantly wasn't in the new inventory
                    if (count == afterMerged.Count - 1) {
                        // Log it
                        result.AddLast(
                            new BlissHiveLogActivityItem(-1, item,
                                    after.originalLogEntry.timestamp));
                    }
                    // Increase the count
                    count++;
                }
            }

            // Comparing items that are now in the inventory,
            // but weren't there before
            //
            // For each item which was in the inventory after
            foreach (BlissHiveLogItem item in afterMerged) {
                int count = 0;
                // For each item that was in the inventory before
                foreach (BlissHiveLogItem otherItem in beforeMerged) {
                    // Can't compare inventory items to backpack items
                    if (item.location == otherItem.location) {
                        // If the key is the same
                        if (otherItem.key == item.key) {
                            // We already checked it above, skip it
                            break;
                        }
                    }
                    // If the item apparantly wasn't in the old inventory
                    if (count == beforeMerged.Count - 1) {
                        // Log it
                        result.AddLast(
                            new BlissHiveLogActivityItem(1, item,
                                    after.originalLogEntry.timestamp));
                    }
                    count++;
                }
            }

            return result;
        }
        public override LogParseResult Parse()
        {
            LinkedList<LogParseResultEntry> result = new LinkedList<LogParseResultEntry>();

            int count = 0;
            /*
             * 0 = ID
             * 1 = Position     [???,[x, y, z?]]
             * 2 = Inventory    [[<tool>, <sidearm>, <mainWeapon>], [<sidearm>, <item>]]
             * 3 = Backpack     [<backpackName>, [[<weapon>], [qty]], [[<item1>, <item2>], [<item1Qty>, [item2Qty]]]
             * 4 = Medical      [false,false,false,true,false,false,true,11714.7,["aimpoint"],[0,0],0,[159.803,247.991]] ??
             *                  [Probably broken bones, fever, etc here ,<blood>,    rest unknown
             * 5 = lastAte,     0 || 1
             * 6 = lastDrank,   0 || 1
             * 7 = survivalTime
             * 8 = model      Seems to be 'any' all the time, but perhaps 'hero' and 'bandit' are values as well
             * 9 = humanity
             * 10 = zombiekills
             * 11 = headshots
             * 12 = murders
             * 13 = banditkills
             * 14 = state       ["M16A2","ainvpknlmstpslaywrfldnon_medic",100]
             *                  [<equiped weapon?>, <gibberish>, <???>]
             **/
            BlissHiveLogContainer blissHiveLogContainer = (BlissHiveLogContainer)this.container;

            LinkedList<String> functionList = new LinkedList<String>();
            foreach (BlissHiveLogEntry entry in container.logs) {

                if (!functionList.Contains(entry.functionName))
                    functionList.AddLast(entry.functionName);

                if (entry.functionName == "proc_updateSurvivor") {
                    BlissHiveLogInventory inventory = new BlissHiveLogInventory(entry);

                    String inventoryParam = entry.parameters[2];
                    // No point parsing empty inventories
                    if (inventoryParam != "[]") {

                        String[] invTypes = inventoryParam.Split(new String[1] { "],[" }, StringSplitOptions.None);
                        String[] invWeapons = invTypes[0]
                                                .Replace("[[", "")
                                                .Replace("\"", "")
                                                .Split(',');

                        String[] invItems = invTypes[1]
                                                .Replace("]]", "")
                                                .Replace("\"", "")
                                                .Replace("[", "")
                                                .Replace("]", "")
                                                .Split(',');

                        foreach (String weapon in invWeapons) {
                            inventory.items.AddLast(new BlissHiveLogItem(weapon, BlissHiveLogItem.Location.Inventory));
                        }

                        foreach (String item in invItems) {
                            int number = 0;
                            // Sometimes, the item is a number (ammo for previous ammo clip).
                            // We don't want those as an item.
                            if( !Int32.TryParse(item, out number) ){
                                inventory.items.AddLast(new BlissHiveLogItem(item, BlissHiveLogItem.Location.Inventory));
                            }
                        }
                    }
                    String backpackParam = entry.parameters[3];
                    // No point parsing empty inventories
                    Boolean addedWeapon = false, addedItem = false;
                    if (backpackParam != "[]") {

                        String[] backpackTypes = backpackParam
                                    .Split(new String[1] { "],[" }, StringSplitOptions.None);

                        String[] temp = backpackTypes[0]
                                    .Split(new String[1] { ",[[" }, StringSplitOptions.None);
                        String backpackName = temp[0]
                                    .Replace("[", "")
                                    .Replace("\"", "");
                        String[] backpackWeapons = new String[0];
                        String[] backpackQuantities = new String[0];
                        String[] backpackItems = new String[0];
                        String[] backpackItemQuantities = new String[0];

                        // If there's weapons in the backpack
                        if (temp.Length > 1) {
                            backpackWeapons = temp[1]
                                        .Replace("\"", "")
                                        .Split(',');
                            backpackQuantities = backpackTypes[1]
                                        .Replace("]", "")
                                        .Split(',');
                        }

                        // If there's items in the backpack
                        if (backpackTypes.Length > 2) {
                            backpackItems = backpackTypes[2]
                                        .Replace("[", "")
                                        .Replace("\"", "")
                                        .Split(',');
                            backpackItemQuantities = backpackTypes[3]
                                        .Replace("]]]", "")
                                        .Split(',');
                        }

                        inventory.items.AddLast(
                            new BlissHiveLogItem(backpackName, BlissHiveLogItem.Location.Backpack));

                        int itemCount = 0;
                        foreach (String backpackWeapon in backpackWeapons) {
                            if (backpackWeapon == "")
                                continue;
                            inventory.items.AddLast(
                                new BlissHiveLogItem(
                                    backpackWeapon,
                                    BlissHiveLogItem.Location.Backpack,
                                    Int32.Parse(backpackQuantities[itemCount])
                                )
                            );
                            addedWeapon = true;
                            itemCount++;
                        }

                        itemCount = 0;
                        foreach (String backpackItem in backpackItems) {
                            if (backpackItem == "")
                                continue;
                            inventory.items.AddLast(
                                new BlissHiveLogItem(
                                    backpackItem,
                                    BlissHiveLogItem.Location.Backpack,
                                    Int32.Parse(backpackItemQuantities[itemCount])
                                )
                            );
                            addedItem = true;
                            itemCount++;
                        }
                    }

                    // If both the inventory and the backpack has changed
                    // if (inventoryParam != "[]" && backpackParam != "[]") {
                    // }

                    if (inventoryParam != "[]" || backpackParam != "[]" &&
                        (addedItem || addedWeapon )) {
                        foreach (BlissHiveLogSurvivor survivor in
                            blissHiveLogContainer.survivorContainer.survivors) {
                            if (survivor.survivorUpdateID == entry.parameters[0]) {
                                // Groups the items for easier readability
                                inventory.GroupItems();
                                survivor.inventories.AddLast(inventory);
                            }
                        }
                        result.AddLast(new BlissHiveSurvivorInventoryLogParseResultEntry(entry));
                    }

                } else if (entry.functionName == "proc_killSurvivor") {

                }

                this.onParseProgressListeners(count, this.container.logs.Length);
                count++;
            }

            foreach (String function in functionList) {
                Console.WriteLine(function);
            }

            this.onParseProgressListeners = null;
            return new LogParseResult(result);
        }