/// <summary>
 /// Converts a <see cref="SourceEntity"/> to a <see cref="Source"/>.
 /// </summary>
 /// <param name="entity">The <see cref="Source"/> that has to be converted.</param>
 /// <returns>The <see cref="Source"/> object.</returns>
 public Source SourceEntityToSource(SourceEntity entity)
 {
     return new Source()
     {
         Id = entity.Id,
         Value = entity.Value,
         SourceDefinition = SourceDefinitionEntityToSourceDefinition(entity.SourceDefinition),
         CreationTime = entity.CreationTime                
     };
 }
        /// <summary>
        /// This method adds a new question to the database and saves this in a variable
        /// </summary>
        private void initializeTestData()
        {
            using (IntelliCloudContext ctx = new IntelliCloudContext())
            {
                UserEntity newUser = new UserEntity();
                newUser.CreationTime = DateTime.UtcNow;
                newUser.FirstName = "integration";
                newUser.LastName = "test";
                newUser.Type = Common.DataTransfer.UserType.Customer;

                ctx.Users.Add(newUser);
                ctx.SaveChanges();

                UserEntity newEmployee = new UserEntity();
                newEmployee.CreationTime = DateTime.UtcNow;
                newEmployee.FirstName = "employee";
                newEmployee.Type = Common.DataTransfer.UserType.Employee;

                ctx.Users.Add(newEmployee);
                ctx.SaveChanges();

                this.employee = newEmployee;

                SourceEntity newSource = new SourceEntity();
                newSource.User = newUser;
                newSource.Value = "*****@*****.**";
                newSource.CreationTime = DateTime.UtcNow;
                newSource.SourceDefinition = new SourceDefinitionEntity { CreationTime = DateTime.UtcNow, Description = "integration test def", Name = "test def", Url = "" };

                ctx.Sources.Add(newSource);
                ctx.SaveChanges();

                QuestionEntity newEntity = new QuestionEntity();
                newEntity.IsPrivate = false;
                newEntity.LanguageDefinition = new LanguageDefinitionEntity { Name = "English", ResourceName = "English" };
                newEntity.QuestionState = Common.DataTransfer.QuestionState.Open;
                newEntity.Source = new QuestionSourceEntity { Source = newSource, PostId = "" };
                newEntity.Title = "this is a test question";
                newEntity.User = newUser;
                newEntity.Content = "this is the question i want to ask, please help me?";
                newEntity.CreationTime = DateTime.UtcNow;
                newEntity.FeedbackToken = "feedbackyeah!!@#$%^&*()";

                ctx.Questions.Add(newEntity);
                ctx.SaveChanges();

                this.entity = newEntity;
            }
        }
        public void CreateQuestion(
            string source, string reference, string question, string title, string postId = null, bool isPrivate = false)
        {
            Validation.StringCheck(source);
            Validation.StringCheck(reference);
            Validation.StringCheck(question);
            Validation.StringCheck(title);

            using (IntelliCloudContext ctx = new IntelliCloudContext())
            {
                // TODO determine real language 
                LanguageDefinitionEntity languageDefinition = ctx.LanguageDefinitions.SingleOrDefault(ld => ld.Name.Equals("English"));

                // TODO remove exception as you probably want to create the language if it doesn't exist.
                if (languageDefinition == null)
                    throw new NotFoundException("No languageDefinition entity exists with the specified ID.");

                SourceDefinitionEntity sourceDefinition = ctx.SourceDefinitions.SingleOrDefault(sd => sd.Name.Equals(source));

                if (sourceDefinition == null)
                    throw new NotFoundException("The provided source doesn't exists.");

                // Check if the user already exists
                SourceEntity sourceEntity = ctx.Sources.SingleOrDefault(s => s.SourceDefinition.Id == sourceDefinition.Id && s.Value == reference);

                UserEntity userEntity;

                if (sourceEntity != null)
                {
                    // user already has an account, use this
                    userEntity = ctx.Users.Single(u => u.Id == sourceEntity.UserId);
                }
                else
                {
                    // user has no account, create one
                    userEntity = new UserEntity()
                    {
                        CreationTime = DateTime.UtcNow,
                        Type = UserType.Customer
                    };

                    ctx.Users.Add(userEntity);

                    // Mount the source to the new user
                    sourceEntity = new SourceEntity()
                    {
                        Value = reference,
                        CreationTime = DateTime.UtcNow,
                        SourceDefinition = sourceDefinition,
                        User = userEntity,
                    };

                    ctx.Sources.Add(sourceEntity);
                }

                QuestionEntity questionEntity = new QuestionEntity()
                {
                    Content = question,
                    CreationTime = DateTime.UtcNow,
                    IsPrivate = isPrivate,
                    QuestionState = QuestionState.Open,
                    Title = title,
                    Source = new QuestionSourceEntity()
                    {
                        Source = sourceEntity,
                        PostId = postId
                    },
                    LanguageDefinition = languageDefinition,
                    User = userEntity
                };

                ctx.Questions.Add(questionEntity);

                ctx.SaveChanges();
            }
        }
        /// <summary>
        /// Method used for creating a new user.
        /// </summary>
        /// <param name="type">The type of user. Required.</param>
        /// <param name="sources">A list of UserSource instances. Required (must contain at least one item).</param>
        /// <param name="firstName">The user's first name. Optional.</param>
        /// <param name="infix">The user's infix. Optional.</param>
        /// <param name="lastName">The user's last name. Optional.</param>
        public void CreateUser(UserType type, IList<UserSource> sources, string firstName = null, string infix = null, string lastName = null)
        {
            // Validate supplied input data
            if (firstName != null) Validation.StringCheck(firstName);
            if (infix != null) Validation.StringCheck(infix);
            if (lastName != null) Validation.StringCheck(lastName);

            using (IntelliCloudContext context = new IntelliCloudContext())
            {
                // Create a new user based on the retrieved user info
                UserEntity userEntity = new UserEntity()
                {
                    FirstName = firstName,
                    Infix = infix,
                    LastName = lastName,
                    Type = type,
                    CreationTime = DateTime.UtcNow
                };
                context.Users.Add(userEntity);

                // Add all supplied sources to the user
                foreach (UserSource source in sources)
                {
                    // Check if the source is defined
                    Validation.SourceDefinitionExistsCheck(source.Name);

                    // Create a new source for the source definition
                    SourceDefinitionEntity sourceDefinition = context.SourceDefinitions.SingleOrDefault(sd => sd.Name.Equals(source.Name));
                    SourceEntity sourceEntity = new SourceEntity()
                    {
                        Value = source.Value,
                        CreationTime = DateTime.UtcNow,
                        SourceDefinition = sourceDefinition,
                        User = userEntity,
                    };
                    context.Sources.Add(sourceEntity);
                }

                // Save the changes to the context
                context.SaveChanges();
            }
        }
        /// <summary>
        /// Method for creating a new user based on an instance of class OpenIDUserInfo.
        /// </summary>
        /// <param name="userInfo">The instance of class OpenIDUserInfo that will be used to create the new user.</param>
        /// <param name="createdUser">Reference to an object of class User - will be set to an instance of class User on success or null if the user could not be created.</param>
        /// <returns>Boolean value indicating if the user could be created.</returns>
        public bool TryCreateNewUser(OpenIDUserInfo userInfo, out User createdUser)
        {
            // User object that will contain the newly created User object on success
            createdUser = null;

            // Only attempt to create a new user when an instance of class OpenIDUserInfo has been supplied
            if (userInfo != null)
            {
                // No user could be matched; create a new user based on the retrieved user info
                UserEntity userEntity = null;
                using (IntelliCloudContext context = new IntelliCloudContext())
                {
                    // Create a new user based on the retrieved user info
                    userEntity = new UserEntity()
                    {
                        FirstName = userInfo.GivenName,
                        LastName = userInfo.FamilyName,
                        Type = UserType.Customer,
                        CreationTime = DateTime.UtcNow
                    };
                    context.Users.Add(userEntity);

                    // Create a new source for the user's email address
                    SourceDefinitionEntity mailSourceDefinition = context.SourceDefinitions.SingleOrDefault(sd => sd.Name.Equals("Mail"));
                    SourceEntity mailSourceEntity = new SourceEntity()
                    {
                        Value = userInfo.Email,
                        CreationTime = DateTime.UtcNow,
                        SourceDefinition = mailSourceDefinition,
                        User = userEntity,
                    };
                    context.Sources.Add(mailSourceEntity);

                    // Create a new source for the user's id from the issuer
                    SourceDefinitionEntity issuerSourceDefinition = context.SourceDefinitions.SingleOrDefault(sd => sd.Name.Equals(userInfo.Issuer));
                    SourceEntity issuerSourceEntity = new SourceEntity()
                    {
                        Value = userInfo.Sub,
                        CreationTime = DateTime.UtcNow,
                        SourceDefinition = issuerSourceDefinition,
                        User = userEntity,
                    };
                    context.Sources.Add(issuerSourceEntity);

                    // Save the changes to the context
                    context.SaveChanges();
                }

                // Convert the UserEntity instance to an instance of class User and set it in the matchedUser variable
                createdUser = this.convertEntities.UserEntityToUser(userEntity);
            }

            // Return true or false indicating if the user has been created
            return (createdUser != null) ? true : false;
        }