/// <summary>
        /// Add new data collector.
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public GXDataCollectorUpdateResponse Put(GXDataCollectorUpdateRequest request)
        {
            GXAmiDataCollector[] collectors = request.Collectors;
            IAuthSession         s          = this.GetSession(false);
            long id;
            List <GXEventsItem> events = new List <GXEventsItem>();

            lock (Db)
            {
                string lastIP;
#if !SS4
                lastIP = GuruxAMI.Server.AppHost.GetIPAddress(base.RequestContext);
#else
                lastIP = "";//TODO;
#endif
                using (var trans = Db.OpenTransaction(IsolationLevel.ReadCommitted))
                {
                    if (long.TryParse(s.Id, out id))
                    {
                        //Normal user can't change add new data collectors.
                        if (!GuruxAMI.Server.GXBasicAuthProvider.CanEditDevice(s))
                        {
                            throw new ArgumentException("Access denied.");
                        }
                        bool superAdmin = GuruxAMI.Server.GXBasicAuthProvider.IsSuperAdmin(s);
                        //If user want's to add new data collectors.
                        if (request.Collectors != null)
                        {
                            foreach (GXAmiDataCollector collector in request.Collectors)
                            {
                                if (collector.Id == 0)
                                {
                                    collector.Guid  = Guid.NewGuid();
                                    collector.Added = DateTime.Now.ToUniversalTime();
                                    Db.Insert(collector);
#if !SS4
                                    collector.Id = (ulong)Db.GetLastInsertId();
#else
                                    collector.Id = (ulong)Db.LastInsertId();
#endif
                                    events.Add(new GXEventsItem(ActionTargets.DataCollector, Actions.Add, collector));
                                }
                                else
                                {
                                    //If DC is added to user group it's state is no longer unassigned.
                                    bool assigned = false;
                                    if (collector.UnAssigned && request.UserGroupIDs != null)
                                    {
                                        events.Add(new GXEventsItem(ActionTargets.DataCollector, Actions.Remove, collector.Clone()));
                                        assigned             = true;
                                        collector.UnAssigned = false;
                                    }
                                    Db.UpdateOnly(collector, p => p.MAC, p => p.Id == collector.Id);
                                    Db.UpdateOnly(collector, p => p.UnAssigned, p => p.Id == collector.Id);
                                    Db.UpdateOnly(collector, p => p.Name, p => p.Id == collector.Id);
                                    Db.UpdateOnly(collector, p => p.Description, p => p.Id == collector.Id);
                                    //If DC is assigned remove it first and then add like assigned.
                                    if (assigned)
                                    {
                                        events.Add(new GXEventsItem(ActionTargets.DataCollector, Actions.Add, collector));
                                    }
                                    else
                                    {
                                        events.Add(new GXEventsItem(ActionTargets.DataCollector, Actions.Edit, collector));
                                    }
                                }
                                //If data collector is added to device group.
                                if (request.UserGroupIDs != null)
                                {
                                    foreach (long it in request.UserGroupIDs)
                                    {
                                        //Can user access user group.
                                        if (!superAdmin && !GXUserGroupService.CanAccess(Db, id, it))
                                        {
                                            throw new ArgumentException("Access denied.");
                                        }
                                        //Check that DC is not already added to the user group.
                                        List <GXAmiDataCollectorUserGroup> dcu = Db.Select <GXAmiDataCollectorUserGroup>(q => q.DataCollectorID == collector.Id && q.UserGroupID == it);
                                        if (dcu.Count == 0)
                                        {
                                            GXAmiDataCollectorUserGroup u = new GXAmiDataCollectorUserGroup();
                                            u.DataCollectorID = collector.Id;
                                            u.UserGroupID     = it;
                                            Db.Insert(u);
#if !SS4
                                            GXAmiUserGroup ug = Db.QueryById <GXAmiUserGroup>(it);
#else
                                            GXAmiUserGroup ug = Db.SingleById <GXAmiUserGroup>(it);
#endif
                                            events.Add(new GXEventsItem(ActionTargets.UserGroup, Actions.Edit, ug));
                                        }
                                    }
                                }
                            }
                        }
                        //User is adding collector by MAC address.
                        else if (request.MacAddress != null)
                        {
                            GXAmiDataCollector it = new GXAmiDataCollector();
                            collectors     = new GXAmiDataCollector[] { it };
                            it.Guid        = Guid.NewGuid();
                            s.UserAuthName = it.Guid.ToString();
                            it.Added       = DateTime.Now.ToUniversalTime();
                            it.IP          = lastIP;
                            it.UnAssigned  = true;
                            if (request.MacAddress != null)
                            {
                                it.MAC = MacToString(request.MacAddress);
                            }
                            Db.Insert(it);
#if !SS4
                            it.Id = (ulong)Db.GetLastInsertId();
#else
                            it.Id = (ulong)Db.LastInsertId();
#endif
                            events.Add(new GXEventsItem(ActionTargets.DataCollector, Actions.Add, it));
                        }
                        else
                        {
                            throw new ArgumentNullException("MAC Address.");
                        }
                    }
                    else
                    {
                        //DC is updating itself.
                        if (request.MacAddress == null)
                        {
                            Guid guid;
                            if (!GuruxAMI.Server.GXBasicAuthProvider.IsGuid(s.Id, out guid))
                            {
                                throw new ArgumentException("Access denied.");
                            }
                            List <GXAmiDataCollector> tmp = Db.Select <GXAmiDataCollector>(q => q.Guid == guid);
                            if (tmp.Count != 1)
                            {
                                throw new ArgumentException("Access denied.");
                            }
                            foreach (GXAmiDataCollector col in request.Collectors)
                            {
                                col.IP = lastIP;
                                Db.Update(col);
                                collectors = request.Collectors;
                                events.Add(new GXEventsItem(ActionTargets.DataCollector, Actions.Edit, col));
                            }
                        }
                        else
                        {
                            List <GXAmiDataCollector> tmp = Db.Select <GXAmiDataCollector>(q => q.MAC == MacToString(request.MacAddress));
                            //If data collector is adding itself.
                            //Check if DC is already try to add itself.
                            if (tmp.Count == 0)
                            {
                                GXAmiDataCollector it = new GXAmiDataCollector();
                                collectors     = new GXAmiDataCollector[] { it };
                                it.Guid        = Guid.NewGuid();
                                s.UserAuthName = it.Guid.ToString();
                                it.Added       = DateTime.Now.ToUniversalTime();
                                it.IP          = lastIP;
                                it.UnAssigned  = true;
                                if (request.MacAddress != null)
                                {
                                    it.MAC = MacToString(request.MacAddress);
                                }
                                Db.Insert(it);
#if !SS4
                                it.Id = (ulong)Db.GetLastInsertId();
#else
                                it.Id = (ulong)Db.LastInsertId();
#endif
                                events.Add(new GXEventsItem(ActionTargets.DataCollector, Actions.Add, it));
                            }
                            else
                            {
                                collectors = new GXAmiDataCollector[] { tmp[0] };
                            }
                        }
                    }
                    //Accept changes.
                    trans.Commit();
                }
            }
            AppHost host = this.ResolveService <AppHost>();
            host.SetEvents(Db, this.Request, id, events);
            return(new GXDataCollectorUpdateResponse(collectors));
        }
        /// <summary>
        /// Add new data collector.
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public GXDataCollectorUpdateResponse Put(GXDataCollectorUpdateRequest request)
        {
            GXAmiDataCollector[] collectors = request.Collectors;
            IAuthSession s = this.GetSession(false);
            long id;
            List<GXEventsItem> events = new List<GXEventsItem>();
            lock (Db)
            {
                string lastIP;
#if !SS4                
                lastIP = GuruxAMI.Server.AppHost.GetIPAddress(base.RequestContext);
#else
                lastIP = "";//TODO;
#endif                
                using (var trans = Db.OpenTransaction(IsolationLevel.ReadCommitted))
                {
                    if (long.TryParse(s.Id, out id))
                    {
                        //Normal user can't change add new data collectors.
                        if (!GuruxAMI.Server.GXBasicAuthProvider.CanEditDevice(s))
                        {
                            throw new ArgumentException("Access denied.");
                        }
                        bool superAdmin = GuruxAMI.Server.GXBasicAuthProvider.IsSuperAdmin(s);
                        //If user want's to add new data collectors.
                        if (request.Collectors != null)
                        {
                            foreach (GXAmiDataCollector collector in request.Collectors)
                            {
                                if (collector.Id == 0)
                                {
                                    collector.Guid = Guid.NewGuid();
                                    collector.Added = DateTime.Now.ToUniversalTime();
                                    Db.Insert(collector);
#if !SS4
                                    collector.Id = (ulong)Db.GetLastInsertId();
#else
                                    collector.Id = (ulong)Db.LastInsertId();
#endif                                   
                                    events.Add(new GXEventsItem(ActionTargets.DataCollector, Actions.Add, collector));
                                }
                                else
                                {
                                    //If DC is added to user group it's state is no longer unassigned.
                                    bool assigned = false;
                                    if (collector.UnAssigned && request.UserGroupIDs != null)
                                    {
                                        events.Add(new GXEventsItem(ActionTargets.DataCollector, Actions.Remove, collector.Clone()));
                                        assigned = true;
                                        collector.UnAssigned = false;
                                    }                                    
                                    Db.UpdateOnly(collector, p => p.MAC, p => p.Id == collector.Id);
                                    Db.UpdateOnly(collector, p => p.UnAssigned, p => p.Id == collector.Id);
                                    Db.UpdateOnly(collector, p => p.Name, p => p.Id == collector.Id);
                                    Db.UpdateOnly(collector, p => p.Description, p => p.Id == collector.Id);
                                    //If DC is assigned remove it first and then add like assigned.
                                    if (assigned)
                                    {
                                        events.Add(new GXEventsItem(ActionTargets.DataCollector, Actions.Add, collector));
                                    }
                                    else
                                    {
                                        events.Add(new GXEventsItem(ActionTargets.DataCollector, Actions.Edit, collector));
                                    }
                                }
                                //If data collector is added to device group.
                                if (request.UserGroupIDs != null)
                                {
                                    foreach (long it in request.UserGroupIDs)
                                    {
                                        //Can user access user group.
                                        if (!superAdmin && !GXUserGroupService.CanAccess(Db, id, it))
                                        {
                                            throw new ArgumentException("Access denied.");
                                        }
                                        //Check that DC is not already added to the user group.
                                        List<GXAmiDataCollectorUserGroup> dcu = Db.Select<GXAmiDataCollectorUserGroup>(q => q.DataCollectorID == collector.Id && q.UserGroupID == it);
                                        if (dcu.Count == 0)
                                        {
                                            GXAmiDataCollectorUserGroup u = new GXAmiDataCollectorUserGroup();
                                            u.DataCollectorID = collector.Id;
                                            u.UserGroupID = it;
                                            Db.Insert(u);
#if !SS4
                                            GXAmiUserGroup ug = Db.QueryById<GXAmiUserGroup>(it);
#else
                                            GXAmiUserGroup ug = Db.SingleById<GXAmiUserGroup>(it);
#endif                                           
                                            events.Add(new GXEventsItem(ActionTargets.UserGroup, Actions.Edit, ug));
                                        }
                                    }
                                }
                            }
                        }
                        //User is adding collector by MAC address.
                        else if (request.MacAddress != null)
                        {
                            GXAmiDataCollector it = new GXAmiDataCollector();
                            collectors = new GXAmiDataCollector[] { it };
                            it.Guid = Guid.NewGuid();
                            s.UserAuthName = it.Guid.ToString();
                            it.Added = DateTime.Now.ToUniversalTime();
                            it.IP = lastIP;
                            it.UnAssigned = true;
                            if (request.MacAddress != null)
                            {
                                it.MAC = MacToString(request.MacAddress);
                            }
                            Db.Insert(it);
#if !SS4
                            it.Id = (ulong)Db.GetLastInsertId();
#else
                            it.Id = (ulong)Db.LastInsertId();
#endif                            
                            events.Add(new GXEventsItem(ActionTargets.DataCollector, Actions.Add, it));
                        }
                        else
                        {
                            throw new ArgumentNullException("MAC Address.");
                        }
                    }
                    else
                    {
                        //DC is updating itself.
                        if (request.MacAddress == null)
                        {
                            Guid guid;
                            if (!GuruxAMI.Server.GXBasicAuthProvider.IsGuid(s.Id, out guid))
                            {
                                throw new ArgumentException("Access denied.");
                            }
                            List<GXAmiDataCollector> tmp = Db.Select<GXAmiDataCollector>(q => q.Guid == guid);
                            if (tmp.Count != 1)
                            {
                                throw new ArgumentException("Access denied.");
                            }
                            foreach (GXAmiDataCollector col in request.Collectors)
                            {
                                col.IP = lastIP;
                                Db.Update(col);
                                collectors = request.Collectors;
                                events.Add(new GXEventsItem(ActionTargets.DataCollector, Actions.Edit, col));
                            }
                        }
                        else
                        {
                            List<GXAmiDataCollector> tmp = Db.Select<GXAmiDataCollector>(q => q.MAC == MacToString(request.MacAddress));
                            //If data collector is adding itself.
                            //Check if DC is already try to add itself.                    
                            if (tmp.Count == 0)
                            {
                                GXAmiDataCollector it = new GXAmiDataCollector();
                                collectors = new GXAmiDataCollector[] { it };
                                it.Guid = Guid.NewGuid();
                                s.UserAuthName = it.Guid.ToString();
                                it.Added = DateTime.Now.ToUniversalTime();
                                it.IP = lastIP;
                                it.UnAssigned = true;
                                if (request.MacAddress != null)
                                {
                                    it.MAC = MacToString(request.MacAddress);
                                }
                                Db.Insert(it);
#if !SS4
                                it.Id = (ulong)Db.GetLastInsertId();
#else
                                it.Id = (ulong)Db.LastInsertId();
#endif                                
                                events.Add(new GXEventsItem(ActionTargets.DataCollector, Actions.Add, it));
                            }
                            else
                            {
                                collectors = new GXAmiDataCollector[] { tmp[0] };
                            }
                        }
                    }
                    //Accept changes.
                    trans.Commit();
                }
            }
            AppHost host = this.ResolveService<AppHost>();
            host.SetEvents(Db, this.Request, id, events);
            return new GXDataCollectorUpdateResponse(collectors);
        }