public void Add(RiftEncounter encounter)
        {
            var encounterData = new RiftEncounterData(encounter.Id, encounter.Name, encounter.StartTime, encounter.StopTime, encounter.Outcome);

            var entityList = new List<RiftEntityData>();

            bool isUploadSupported = false;
            foreach (var riftEntity in encounter.EntityMap)
            {
                if (_bossArchive.Contains(riftEntity.Value.Name))
                {
                    encounterData.IsBossEncounter = true;
                }

                if (_bossArchive.GetRaidBosses().Contains(riftEntity.Value.Name) && riftEntity.Value.Name.Equals(encounter.Name))
                {
                    isUploadSupported = true;
                }

                if (!riftEntity.Value.IsPlayer) continue;

                var existingEntity = _entityList.SingleOrDefault(x => x.Name.ToLowerInvariant().Trim() == riftEntity.Value.Name.ToLowerInvariant().Trim() && x.EncounterId == encounter.Id);

                if (existingEntity != null)
                {
                    // Merge new data onto existing entity
                    var entityCasts = encounter.getActions().Where(x => x.CasterId == riftEntity.Value.Id);

                    foreach (var entityCast in entityCasts)
                    {
                        entityCast.CasterId = existingEntity.Id;
                    }
                    var entityReceives = encounter.getActions().Where(x => x.TargetId == riftEntity.Value.Id);

                    foreach (var entityCast in entityReceives)
                    {
                        entityCast.TargetId = existingEntity.Id;
                    }
                }
                else
                {
                    var entityData = new RiftEntityData(encounter.Id, riftEntity.Value.Id, riftEntity.Value.OwnerId, riftEntity.Value.Name, riftEntity.Value.IsPlayer, riftEntity.Value.Relationship);

                    entityList.Add(entityData);
                }
            }

            if (!isUploadSupported && !encounter.IsBossEncounter)
                return;

            IList<RiftActionData> actionList = new List<RiftActionData>();

            lock (locker)
            {
                _entityList.AddRange(entityList);

                actionList = encounter.getActions().Select(action => new RiftActionData(encounter.Id, action.ActionType, action.CasterId, action.TargetId, action.SpellId, action.SpellValue, action.Overheal, action.Intercepted, action.Blocked, action.Absorbed, action.Overkill, action.DamageType, action.Timestamp)).ToList();
                _actionList.AddRange(actionList);

                _encounterList.Add(encounterData);
            }

            var _encounter = new RiftEncounterDescriptor(encounter.Id, encounter.Name, encounter.Duration, encounter.IsBossEncounter, isUploadSupported, encounter.Outcome);
            _encounterDescriptors.Add(_encounter);

            PropertyChanged(this, new PropertyChangedEventArgs("EncounterDescriptors"));
        }
        private static List<string> getTimeline(IList<RiftActionData> actionList, RiftEntityData riftEntity, IList<RiftActionType> filterTypes)
        {
            var damageTimeline = new List<string>();

            var damageSpells = actionList.Where(x => x.CasterId == riftEntity.Id && filterTypes.Contains(x.ActionType)).OrderBy(x => x.Timestamp).ToList();

            if (damageSpells.IsEmpty()) return new List<string>();

            var interval = 3;
            var startTime = damageSpells.Min(x => x.Time);
            var encounterTime = new TimeSpan(0, 0, 0, 0);
            var endTime = damageSpells.Max(x => x.Time);

            var currentTime = startTime;
            while (currentTime <= endTime)
            {
                var amount = damageSpells
                    .Where(x => x.CasterId == riftEntity.Id && x.Time >= startTime && x.Time <= startTime.AddSeconds(interval) && RiftActionFilterFactory.getDamageTypes().Contains(x.ActionType))
                    .Sum(x => x.SpellValue);

                var amountE = amount / interval;

                damageTimeline.Add(string.Format("[{0}, {1}]", encounterTime.ToString(), amountE));
                encounterTime = encounterTime.Add(new TimeSpan(0, 0, 0, interval));
                currentTime = currentTime.AddSeconds(interval);
                startTime = startTime.AddSeconds(interval);
            }

            return damageTimeline;
        }