public Company CreateCompany(string name, string url, byte[] image,
            string email, string password,
            string address1, string address2, string postalCode, string city,
            int country, IEnumerable<int> tagIds)
        {
            using (DataAccessLayer dal = new EFDataAccessLayer())
            {
                using (TransactionScope tr = new TransactionScope())
                {

                    Account account = dal.AccountFactory.Create(0, 0);
                    dal.AccountDAO.Add(account);

                    Address address =
                        dal.AddressFactory.Create(0, address1, address2, postalCode, city, country);
                    dal.AddressDAO.Add(address);

                    Company company = dal.CompanyFactory.Create(0, email, password, DateTime.Now, address.Id,
                                                        account.Id, name, image, url, tagIds);

                    company.Address = address;
                    company.Account = account;

                    dal.CompanyDAO.Add(company);

                    tr.Complete();
                    return company;
                }

            }
        }
        public void CreateUser(PersonDTO person)
        {
            using (DataAccessLayer dal = new EFDataAccessLayer())
            {
                AccountDTO accountDto = dal.AccountDAO.Create(new AccountDTO(null, 0, dal));
                //piwi devia ser assim (bem mais simples): person.Account = accountDto;
                //person.AccountID = accountDto.ID.GetValueOrDefault(0);

                dal.PersonDAO.Create(person);
            }
        }
 public Organization GetOrganization(int organizationId)
 {
     using (DataAccessLayer dal = new EFDataAccessLayer())
     {
         return dal.OrganizationDAO.Read(organizationId);
     }
 }
        public Guid Login(string user, string pass)
        {
            using (DataAccessLayer dal = new EFDataAccessLayer())
            {
                var userDto = dal.PersonDAO.ReadAll().SingleOrDefault(o => o.Email == user);

                if (userDto == null || !userDto.Password.Equals(pass))
                {
                    return Guid.Empty;
                }
            }

            // Em caso afirmativo, criar o ticket
            Ticket t = new Ticket(Guid.NewGuid(), DateTime.Now.AddMinutes(2));

            currTickets.Add(t.TicketId,t);

            return t.TicketId;
        }
        public PersonDTO GetUser(Guid ticket, string user)
        {
            // Validar o ticket
            if (!ValidateTicket(ticket))
            {
                //throw exception
                //throw new AccessViolationException();
                return null;
            }

            using (DataAccessLayer dal = new EFDataAccessLayer())
            {
                return dal.PersonDAO.ReadAll().SingleOrDefault( s => s.Email == user);
            }
        }
 public void CreateEmergency(string title, string description, DateTime startDate, DateTime? endDate, decimal weight, byte[] image, int organizationId)
 {
     using (DataAccessLayer dal = new EFDataAccessLayer())
     {
         using (TransactionScope tr = new TransactionScope())
         {
             Emergency e = dal.EmergencyFactory.Create(0, title, description, startDate, endDate, weight, image, organizationId);
             dal.EmergencyDAO.Add(e);
             tr.Complete();
         }
     }
 }
        public bool Transfer(int from, int to, int organizationId, decimal amount, decimal donation, string reference)
        {
            using (DataAccessLayer dal = new EFDataAccessLayer())
            {
                TransactionOptions options = new TransactionOptions
                                                 {
                                                     IsolationLevel = IsolationLevel.RepeatableRead
                                                 };

                using (TransactionScope tr = new TransactionScope(TransactionScopeOption.Required, options))
                {
                    //obter as contas
                    Person person = dal.PersonDAO.Read(from);
                    if (person == null) throw new Exception("From not found!");

                    Company company = dal.CompanyDAO.Read(to);
                    if (company == null) throw new Exception("To not found!");

                    Organization organization = dal.OrganizationDAO.Read(organizationId);

                    Account fromAccount = person.Account;
                    Account toAccount = company.Account;

                    //transferir o dinheiro e guardar 1 centimo para a caridade
                    if (fromAccount.Value > amount + donation)
                        fromAccount.Value -= amount + donation;
                    else throw new Exception("Not enough money!");

                    toAccount.Value += amount;

                    // adicinar o centimo à conta da organização solidaria
                    Account charityAccount = organization.Account;

                    charityAccount.Value += donation;

                    DAL.DTOs.Transaction tranOCW = dal.TransactionFactory.Create(0, amount, donation, DateTime.Now, reference, person.Id, company.Id, organization.Id);

                    dal.TransactionDAO.Add(tranOCW);

                    // fazer update a tudo
                    dal.AccountDAO.Update(fromAccount);
                    dal.AccountDAO.Update(toAccount);
                    dal.AccountDAO.Update(charityAccount);

                    tr.Complete();
                }
            }

            return true;
        }
 public IEnumerable<IndependentOrganization> ListAllOrganizationsIndependentEntities()
 {
     using (DataAccessLayer dal = new EFDataAccessLayer())
     {
         var orgs = dal.OrganizationDAO.ReadAll();
         List<IndependentOrganization> io = new List<IndependentOrganization>();
         foreach (var org in orgs)
         {
             io.Add(new IndependentOrganization()
             {
                 Name = org.Name,
                 Id = org.Id,
             }
             );
         }
         return io;
     }
 }
 public Person GetPerson(string email)
 {
     using (DataAccessLayer dal = new EFDataAccessLayer())
     {
         return dal.ProfileDAO.FindByEmail(email) as Person;
     }
 }
 public Person GetPerson(int userId)
 {
     using (DataAccessLayer dal = new EFDataAccessLayer())
     {
         return dal.PersonDAO.Read(userId);
     }
 }
        public IEnumerable<DAL.DTOs.Transaction> GetOrganizationTransactions(string organizationEmail)
        {
            using (DataAccessLayer dal = new EFDataAccessLayer())
            {
                Organization organization = dal.ProfileDAO.FindByEmail(organizationEmail) as Organization;

                return organization == null ? null : organization.Transaction;
            }
        }
        public Organization GetOrganizationFullInfo(string email)
        {
            using (DataAccessLayer dal = new EFDataAccessLayer())
            {
                Organization o = dal.OrganizationDAO.ReadAll(where => where.Email == email).First();

                o.Address = dal.AddressDAO.Read(o.Address_id);
                o.Address.Country = dal.CountryDAO.Read(o.Address.Country_id);
                o.Tag.ToList();

                return o;
            }
        }
        public Organization GetOrganizationFromCompany(int companyId)
        {
            using (DataAccessLayer dal = new EFDataAccessLayer())
            {
                Organization org = null;

                IEnumerable<Emergency> emergencies = GetActiveEmergencies();
                foreach (var emergency in emergencies)
                {
                    Random random = new Random();
                    int next = random.Next(0, 100);
                    if (next <= emergency.Weight * 100) return emergency.Organization;
                }

                Company c = dal.CompanyDAO.Read(companyId);

                List<Organization> o = new List<Organization>();
                foreach (Tag tag in c.Tag)
                {
                    foreach (Organization organization in tag.Organization)
                    {
                        if(!o.Contains(organization)) o.Add(organization);
                    }
                }

                return o.Count > 0 ? o.Random() : dal.OrganizationDAO.ReadAll().ToList().Random();
            }
        }
 public Organization GetOrganization(string email)
 {
     using (DataAccessLayer dal = new EFDataAccessLayer())
     {
         return dal.ProfileDAO.FindByEmail(email) as Organization;
     }
 }
 public IEnumerable<String> ListAllCountries()
 {
     using (DataAccessLayer dal = new EFDataAccessLayer())
     {
         return dal.CountryDAO.ReadAll().Select(o => o.Name).ToList();
     }
 }
        public Person GetPersonFullInfo(string email)
        {
            using (DataAccessLayer dal = new EFDataAccessLayer())
            {
                Person p =  dal.ProfileDAO.FindByEmail(email) as Person;

                p.Address = dal.AddressDAO.Read(p.Address_id);
                p.Address.Country = dal.CountryDAO.Read(p.Address.Country_id);

                return p;
            }
        }
 public IEnumerable<string> ListAllOrganizations()
 {
     using (DataAccessLayer dal = new EFDataAccessLayer())
     {
         return dal.OrganizationDAO.ReadAll().Select(o => o.Name).ToList();
     }
 }
 public IEnumerable<DAL.DTOs.Transaction> GetPersonTransactions(string personEmail)
 {
     using (DataAccessLayer dal = new EFDataAccessLayer())
     {
         using (TransactionScope tr = new TransactionScope())
         {
             Person person = dal.ProfileDAO.FindByEmail(personEmail) as Person;
             return person == null ? null : person.Transaction;
         }
     }
 }
        public Profile Login(string email, string pass)
        {
            using (DataAccessLayer dal = new EFDataAccessLayer())
            {
                var profile = dal.ProfileDAO.FindByEmail(email);

                return profile != null && profile.Password.Equals(pass) ? profile : null;
            }
        }
        public Profile GetProfile(string profileEmail)
        {
            using (DataAccessLayer dal = new EFDataAccessLayer())
            {
                Profile profile = dal.ProfileDAO.FindByEmail(profileEmail);

                return profile;
            }
        }
        public bool Withdraw(int from, decimal amount, string destination)
        {
            using (DataAccessLayer dal = new EFDataAccessLayer())
            {
                TransactionOptions options = new TransactionOptions
                {
                    IsolationLevel = IsolationLevel.RepeatableRead
                };

                using (TransactionScope tr = new TransactionScope(TransactionScopeOption.Required, options))
                {
                    //obter as contas
                    Profile profile = dal.ProfileDAO.Read(from);
                    Account fromAccount = profile.Account;

                    //remover o dinheiro
                    if (fromAccount.Value >= amount)
                    {
                        fromAccount.Value -= amount;
                        dal.AccountDAO.Update(fromAccount);
                        var wtd = dal.WithdrawFactory.Create(0, DateTime.Now, amount, destination, from);
                        dal.WithdrawDAO.Add(wtd);
                    }
                    else return false;

                    tr.Complete();
                }
            }
            return true;
        }
 public string GetProfileType(string email)
 {
     using (DataAccessLayer dal = new EFDataAccessLayer())
     {
         return "";
     }
 }
        public PersonDTO GetUser(Guid ticket, int userId)
        {
            // Validar o ticket
            if (!ValidateTicket(ticket))
            {
                //throw exception
                //throw new AccessViolationException();
                return null;
            }

            using (DataAccessLayer dal = new EFDataAccessLayer())
            {
                return dal.PersonDAO.Read(userId);
            }
        }
        public Profile GetProfileWithAccount(string email)
        {
            using (DataAccessLayer dal = new EFDataAccessLayer())
            {
                Profile p = dal.ProfileDAO.FindByEmail(email);

                p.Account = dal.AccountDAO.Read(p.Account_id);
                return p;
            }
        }
        public Guid Login(int userID, string pass)
        {
            // Validar utilizador
            using (DataAccessLayer dal = new EFDataAccessLayer())
            {
                var user = dal.PersonDAO.Read(userID);

                if (user == null || !user.Password.Equals(pass))
                {
                    return Guid.Empty;
                }
            }

            // Em caso afirmativo, criar o ticket
            Ticket t = new Ticket(Guid.NewGuid(), DateTime.Now.AddMinutes(2));

            currTickets.Add(t.TicketId,t);

            return t.TicketId;
        }
        public IEnumerable<DAL.DTOs.Transaction> GetTransactionsbyId(int id)
        {
            List<DAL.DTOs.Transaction> transactions = new List<DAL.DTOs.Transaction>();

            using (DataAccessLayer dal = new EFDataAccessLayer())
            {
                var allTransactions = dal.TransactionDAO.ReadAllFull(w => w.Organization_id == id || w.Company_id == id || w.Person_id == id);

                //if (allTransactions == null)
                //{
                //    return new List<DAL.DTOs.Transaction>().AsEnumerable();
                //}

                return allTransactions.ToList();
            }
            try
            {
                Company company = GetCompany(id);
                if (company.Transaction.Count > 0) transactions.AddRange(company.Transaction);
            }catch(RecordNotFoundException<int>){}

            try
            {
                Organization organization = GetOrganization(id);
                if (organization.Transaction.Count > 0) transactions.AddRange(organization.Transaction);
            }catch(RecordNotFoundException<int>){}

            try
            {
                Person person = GetPerson(id);
                if (person.Transaction.Count > 0) transactions.AddRange(person.Transaction);
            }
            catch (RecordNotFoundException<int>) { }

            return transactions;
        }
        public bool Transfer(Guid ticket, int from, int to, decimal ammount, string[] tags)
        {
            // Validar o ticket
            if (!ValidateTicket(ticket))
            {
                return false;
            }

            using(DataAccessLayer dal = new EFDataAccessLayer())
            {
                using (TransactionScope tr = new TransactionScope())
                {
                    //obter as contas

                    AccountDTO fromAccount = dal.AccountDAO.Read(from);
                    AccountDTO toAccount = dal.AccountDAO.Read(to);

                    //transferir o dinheiro
                    fromAccount.Value -= ammount;
                    toAccount.Value += ammount;

                    //guardar 1Centimo para a caridade
                    fromAccount.Value -= VALOR_CONTRIBUICAO;

                    // adicinar o centimo à conta da organização solidaria

                    // Adicionar transacçao - isto vai demorar longitudes de tempo... uma msmq a fazer isto é melhor
                    ////TODO Falta acabar isto
                    TransactionDTO tranOCW = new TransactionDTO(0,ammount, VALOR_CONTRIBUICAO, DateTime.Now, 0,0,0);
                    dal.TransactionDAO.Create(tranOCW);

                    // fazer update a tudo
                    dal.AccountDAO.Update(fromAccount);
                    dal.AccountDAO.Update(toAccount);

                    tr.Complete();
                }
            }

            return true;
        }
 public IEnumerable<Withdraw> GetWithdrawList(string name)
 {
     using (DataAccessLayer dal = new EFDataAccessLayer())
     {
         int profileId = dal.ProfileDAO.FindByEmail(name).Id;
         return dal.WithdrawDAO.ReadAll().Where(w => w.Profile_id == profileId).ToList();
     }
 }
        public void DeleteUser(Guid ticket, int user)
        {
            // Validar o ticket
            if (!ValidateTicket(ticket))
            {
                //throw exception
                //throw new AccessViolationException();
                return;
            }

            using (DataAccessLayer dal = new EFDataAccessLayer())
            {
                dal.PersonDAO.Delete(user);
            }
        }
 public IndependentOngProfile GetOng(string email)
 {
     using (DataAccessLayer dal = new EFDataAccessLayer())
     {
         var profile = dal.ProfileDAO.FindByEmail(email);
         var ong= dal.OrganizationDAO.Read(profile.Id);
         return profile != null ?
             new IndependentOngProfile()
             {
                 Address1 = profile.Address.Address1,
                 Address2 = profile.Address.Address2,
                 City = profile.Address.City,
                 Country = profile.Address.Country.Id,
                 Email = profile.Email,
                 Name = profile.ProfileName,
                 Password = profile.Password,
                 PostalCode = profile.Address.PostalCode,
                 Url = ong.Url,
                 //TypeId = ong.Tag,
             }
             : null;
     }
 }