/// <summary>
        /// Parses all the data again and link related stuff to each other
        /// </summary>
        private void fillMissingData()
        {
            var agentsLookup = agent_data.getAllAgentsList().ToDictionary(a => a.getAgent());

            bool golem_mode = isGolem(boss_data.getID());

            // Set Agent instid, first_aware and last_aware
            var combat_list = combat_data.getCombatList();

            foreach (CombatItem c in combat_list)
            {
                if (agentsLookup.TryGetValue(c.getSrcAgent(), out var a))
                {
                    if (a.getInstid() == 0 && (c.isStateChange() == ParseEnum.StateChange.Normal || (golem_mode && isGolem(a.getID()) && c.isStateChange() == ParseEnum.StateChange.MaxHealthUpdate)))
                    {
                        a.setInstid(c.getSrcInstid());
                    }
                    if (a.getInstid() != 0)
                    {
                        if (a.getFirstAware() == 0)
                        {
                            a.setFirstAware(c.getTime());
                            a.setLastAware(c.getTime());
                        }
                        else
                        {
                            a.setLastAware(c.getTime());
                        }
                    }
                }
            }

            foreach (CombatItem c in combat_list)
            {
                if (c.getSrcMasterInstid() != 0)
                {
                    var master = agent_data.getAllAgentsList().Find(x => x.getInstid() == c.getSrcMasterInstid() && x.getFirstAware() < c.getTime() && c.getTime() < x.getLastAware());
                    if (master != null)
                    {
                        if (agentsLookup.TryGetValue(c.getSrcAgent(), out var minion) && minion.getFirstAware() < c.getTime() && c.getTime() < minion.getLastAware())
                        {
                            minion.setMasterAgent(master.getAgent());
                        }
                    }
                }
            }

            agent_data.clean();

            // Set Boss data agent, instid, first_aware, last_aware and name
            List <AgentItem> NPC_list      = agent_data.getNPCAgentList();
            HashSet <ulong>  multiple_boss = new HashSet <ulong>();

            foreach (AgentItem NPC in NPC_list)
            {
                if (NPC.getProf().EndsWith(boss_data.getID().ToString()))
                {
                    if (boss_data.getAgent() == 0)
                    {
                        boss_data.setAgent(NPC.getAgent());
                        boss_data.setInstid(NPC.getInstid());
                        boss_data.setFirstAware(NPC.getFirstAware());
                        boss_data.setName(NPC.getName());
                        boss_data.setTough(NPC.getToughness());
                    }
                    multiple_boss.Add(NPC.getAgent());
                    boss_data.setLastAware(NPC.getLastAware());
                }
            }
            if (multiple_boss.Count > 1)
            {
                agent_data.cleanInstid(boss_data.getInstid());
            }

            AgentItem bossAgent = agent_data.GetAgent(boss_data.getAgent());

            boss = new Boss(bossAgent);
            List <Point> bossHealthOverTime = new List <Point>();

            // a hack for buggy golem logs
            if (golem_mode)
            {
                ulong redirection = 0;

                foreach (AgentItem a in agent_data.getAllAgentsList())
                {
                    if (a.getID() == 19603)
                    {
                        redirection = a.getAgent();
                    }
                }

                if (redirection != 0)
                {
                    foreach (CombatItem c in combat_list)
                    {
                        if (c.getDstAgent() == 0 && c.getDstInstid() == 0 && c.isStateChange() == ParseEnum.StateChange.Normal && c.getIFF() == ParseEnum.IFF.Foe && c.isActivation() == ParseEnum.Activation.None)
                        {
                            c.setDstAgent(bossAgent.getAgent());
                            c.setDstInstid(bossAgent.getInstid());
                        }
                    }
                }
            }
            // Grab values threw combat data
            foreach (CombatItem c in combat_list)
            {
                if (c.getSrcInstid() == boss_data.getInstid() && c.isStateChange() == ParseEnum.StateChange.MaxHealthUpdate)//max health update
                {
                    boss_data.setHealth((int)c.getDstAgent());
                }
                switch (c.isStateChange())
                {
                case ParseEnum.StateChange.PointOfView:
                    if (log_data.getPOV() == "N/A")    //Point of View
                    {
                        ulong pov_agent = c.getSrcAgent();
                        if (agentsLookup.TryGetValue(pov_agent, out var p))
                        {
                            log_data.setPOV(p.getName());
                        }
                    }
                    break;

                case ParseEnum.StateChange.LogStart:
                    log_data.setLogStart(c.getValue());
                    break;

                case ParseEnum.StateChange.LogEnd:
                    log_data.setLogEnd(c.getValue());
                    break;

                case ParseEnum.StateChange.HealthUpdate:
                    //set health update
                    if (c.getSrcInstid() == boss_data.getInstid())
                    {
                        bossHealthOverTime.Add(new Point((int)(c.getTime() - boss_data.getFirstAware()), (int)c.getDstAgent()));
                    }
                    break;
                }
            }

            // Dealing with second half of Xera | ((22611300 * 0.5) + (25560600 * 0.5)
            if (boss_data.getID() == 16246)
            {
                int xera_2_instid = 0;
                foreach (AgentItem NPC in NPC_list)
                {
                    if (NPC.getProf().Contains("16286"))
                    {
                        bossHealthOverTime = new List <Point>();//reset boss health over time
                        xera_2_instid      = NPC.getInstid();
                        boss_data.setHealth(24085950);
                        boss.addPhaseData(boss_data.getLastAware());
                        boss.addPhaseData(NPC.getFirstAware());
                        boss_data.setLastAware(NPC.getLastAware());
                        foreach (CombatItem c in combat_list)
                        {
                            if (c.getSrcInstid() == xera_2_instid)
                            {
                                c.setSrcInstid(boss_data.getInstid());
                            }
                            if (c.getDstInstid() == xera_2_instid)
                            {
                                c.setDstInstid(boss_data.getInstid());
                            }
                            //set health update
                            if (c.getSrcInstid() == boss_data.getInstid() && c.isStateChange() == ParseEnum.StateChange.HealthUpdate)
                            {
                                bossHealthOverTime.Add(new Point((int)(c.getTime() - boss_data.getFirstAware()), (int)c.getDstAgent()));
                            }
                        }
                        break;
                    }
                }
            }
            //Dealing with Deimos split
            if (boss_data.getID() == 17154)
            {
                int deimos_2_instid = 0;
                foreach (AgentItem NPC in agent_data.getGadgetAgentList())
                {
                    if (NPC.getProf().Contains("08467") || NPC.getProf().Contains("08471"))
                    {
                        deimos_2_instid = NPC.getInstid();
                        long oldAware = boss_data.getLastAware();
                        if (NPC.getLastAware() < boss_data.getLastAware())
                        {
                            // No split
                            break;
                        }
                        boss.addPhaseData(NPC.getFirstAware() >= oldAware ? NPC.getFirstAware() : oldAware);
                        boss_data.setLastAware(NPC.getLastAware());
                        //List<CombatItem> fuckyou = combat_list.Where(x => x.getDstInstid() == deimos_2_instid ).ToList().Sum(x);
                        //int stop = 0;
                        foreach (CombatItem c in combat_list)
                        {
                            if (c.getTime() > oldAware)
                            {
                                if (c.getSrcInstid() == deimos_2_instid)
                                {
                                    c.setSrcInstid(boss_data.getInstid());
                                }
                                if (c.getDstInstid() == deimos_2_instid)
                                {
                                    c.setDstInstid(boss_data.getInstid());
                                }
                            }
                        }
                        break;
                    }
                }
            }
            boss_data.setHealthOverTime(bossHealthOverTime);//after xera in case of change

            // Re parse to see if the boss is dead and update last aware
            foreach (CombatItem c in combat_list)
            {
                //set boss dead
                if (c.isStateChange() == ParseEnum.StateChange.Reward)//got reward
                {
                    log_data.setBossKill(true);
                    boss_data.setLastAware(c.getTime());
                    break;
                }
                //set boss dead
                if (c.getSrcInstid() == boss_data.getInstid() && c.isStateChange() == ParseEnum.StateChange.ChangeDead && !log_data.getBosskill())//change dead
                {
                    log_data.setBossKill(true);
                    boss_data.setLastAware(c.getTime());
                }
            }

            //players
            if (p_list.Count == 0)
            {
                //Fix Disconected players
                var playerAgentList = agent_data.getPlayerAgentList();

                foreach (AgentItem playerAgent in playerAgentList)
                {
                    List <CombatItem> lp     = combat_data.getStates(playerAgent.getInstid(), ParseEnum.StateChange.Despawn, boss_data.getFirstAware(), boss_data.getLastAware());
                    Player            player = new Player(playerAgent);
                    bool skip = false;
                    foreach (Player p in p_list)
                    {
                        if (p.getAccount() == player.getAccount())//is this a copy of original?
                        {
                            skip = true;
                        }
                    }
                    if (skip)
                    {
                        continue;
                    }
                    if (lp.Count > 0)
                    {
                        //make all actions of other instances to original instid
                        foreach (AgentItem extra in NPC_list)
                        {
                            if (extra.getAgent() == playerAgent.getAgent())
                            {
                                var extra_login_Id = extra.getInstid();
                                foreach (CombatItem c in combat_list)
                                {
                                    if (c.getSrcInstid() == extra_login_Id)
                                    {
                                        c.setSrcInstid(playerAgent.getInstid());
                                    }
                                    if (c.getDstInstid() == extra_login_Id)
                                    {
                                        c.setDstInstid(playerAgent.getInstid());
                                    }
                                }
                                break;
                            }
                        }

                        player.SetDC(lp[0].getTime());
                        p_list.Add(player);
                    }
                    else//didnt dc
                    {
                        if (player.GetDC() == 0)
                        {
                            p_list.Add(player);
                        }
                    }
                }
            }
            // Sort
            p_list = p_list.OrderBy(a => a.getGroup()).ToList();
        }