using System;
using System.Data;
using System.IO;
using System.Configuration;
using System.Web;
using System.Collections.Generic;
using System.Text;
using System.Web.Security;
using XMLProviders;

namespace Helion.CustomProviders.XML
{
   class RoleProvider : System.Web.Security.RoleProvider
   {
      private string name;
      private string roleFIle;
      private string applicationName;
      private RoleDataSet roleData;

      public override string Description
      {
         get { return "DosXML File-Based ASP.NET 2.0 Role Provider"; }
      }

      private void InitializeData()
      {
         roleData = new RoleDataSet();
         if (File.Exists(roleFile))
            roleData.ReadXml(roleFile);
      }

      private void SaveData()
      {
         roleData.AcceptChanges();
         roleData.WriteXml(roleFile);
      }

      public override void Initialize(string name,
          System.Collections.Specialized.NameValueCollection config)
      {
         try
         {
            this.name = name;
            ApplicationName = config["applicationName"];
            roleFile =
                ConfigurationManager.ConnectionStrings[
                    config["connectionStringName"]].ConnectionString;
            InitializeData();
         }
         catch (Exception e)
         {
            System.Diagnostics.Debug.WriteLine(e.ToString());
         }
      }
      public override string Name
      {
         get { return name; }
      }

      public override void AddUsersToRoles(string[] usernames, string[] roleNames)
      {
         foreach (string userName in usernames)
         {
            foreach (string roleName in roleNames)
            {
               int roleId = ((RoleDataSet.RolesRow)
                   roleData.Roles.Select("RoleName='" + roleName + "'")[0]).RoleId;
               RoleDataSet.UsersInRolesRow newRow =
                   roleData.UsersInRoles.NewUsersInRolesRow();
               newRow.UserId = userName;
               newRow.RoleId = roleId;
               roleData.UsersInRoles.AddUsersInRolesRow(newRow);
               SaveData();
            }
         }
      }

      public override string ApplicationName
      {
         get { return applicationName; }
         set
         {
            applicationName = value;
         }
      }

      public override void CreateRole(string roleName)
      {
         RoleDataSet.RolesRow newRole = roleData.Roles.NewRolesRow();
         newRole.RoleName = roleName;
         newRole.ApplicationId = applicationName;
         newRole.Description = roleName;
         roleData.Roles.AddRolesRow(newRole);
         roleData.AcceptChanges();
         SaveData();
      }

      public override bool DeleteRole(string roleName, bool throwOnPopulatedRole)
      {
         RoleDataSet.RolesRow delRole = (RoleDataSet.RolesRow)
             roleData.Roles.Select("RoleName='" + roleName + "'")[0];
         DataRow[] users = roleData.UsersInRoles.Select("RoleId=" + delRole.RoleId);
         if ((users.Length > 0) && (throwOnPopulatedRole))
            throw new
            InvalidOperationException("Cannot delete role to which users are assigned");
         else
         {
            foreach (DataRow userInRole in users)
            {
               userInRole.Delete();
            }
            delRole.Delete();
            roleData.AcceptChanges();
            SaveData();
            return true;
         }
      }

      public override string[] FindUsersInRole(string roleName, string usernameToMatch)
      {
         List<string> al = new List<string>();
         RoleDataSet.UsersInRolesRow[] users =
             (RoleDataSet.UsersInRolesRow[])roleData.Roles.Select(
             "RoleName = '" + roleName + "'");
         foreach (RoleDataSet.UsersInRolesRow user in users)
         {
            if (user.UserId.ToUpper() == usernameToMatch.ToUpper())
               al.Add(user.UserId);
         }
         return al.ToArray();
      }

      public override string[] GetAllRoles()
      {
         List<string> al = new List<string>();
         foreach (RoleDataSet.RolesRow role in
             (RoleDataSet.RolesRow[])
                 roleData.Roles.Select("ApplicationId='" + applicationName + "'"))
         {
            al.Add(role.RoleName);
         }
         return al.ToArray();
      }

      public override string[] GetRolesForUser(string username)
      {
         List<int> roleIds = new List<int>();
         RoleDataSet.UsersInRolesRow[] users =
             (RoleDataSet.UsersInRolesRow[])
                 roleData.UsersInRoles.Select("UserId = '" + username + "'");
         foreach (RoleDataSet.UsersInRolesRow user in users)
            roleIds.Add(user.RoleId);
         List<string> roleNames = new List<string>();
         foreach (int roleId in roleIds)
         {
            RoleDataSetRolesRow theRow =
                (RoleDataSet.RolesRow)roleData.Roles.Select("RoleId=" + roleId)[0];
            if (theRow.ApplicationId.ToUpper() == applicationName.ToUpper())
               roleNames.Add(theRow.RoleName);
         }
         return roleNames.ToArray();
      }

      public override string[] GetUsersInRole(string roleName)
      {
         List<string> users = new List<string>();
         int roleId = GetRoleId(roleName);
         foreach (RoleDataSet.UsersInRolesRow user in
             (RoleDataSet.UsersInRolesRow[])
                 roleData.UsersInRoles.Select("RoleId=" + roleId.ToString()))
         {
            users.Add(user.UserId);
         }
         return users.ToArray();
      }

      private int GetRoleId(string roleName)
      {
         DataRow[] rows = roleData.Roles.Select(
             "RoleName='" + roleName + "'AND ApplicationId='" + applicationName + "'");
         if (rows == null)
            return -1;
         if (rows.Length == 0)
            return -1;
         return ((RoleDataSet.RolesRow)rows[0]).RoleId;
      }

      public override bool IsUserInRole(string username, string roleName)
      {
         int roleId = GetRoleId(roleName);
         RoleDataSet.UsersInRolesRow[] users =
             (RoleDataSet.UsersInRolesRow[])
                 roleData.UsersInRoles.Select("RoleId=" + roleId.ToString());
         return (users.Length > 0);
      }

      public override void RemoveUsersFromRoles(string[] usernames, string[] roleNames)
      {
         foreach (string userId in usernames)
         {
            foreach (string roleName in roleNames)
            {
               int roleId = GetRoleId(roleName);
               RoleDataSet.UsersInRolesRow userRoleRow =
                   ((RoleDataSet.Users.InRolesRow[])
                       roleData.UsersInRoles.Select("UserId='" + userId +
                       "' AND RoleId=" + roleId.ToString()))[0];
               userRoleRow.Delete();
            }
         }
         SaveData();
      }

      public override bool RoleExists(string roleName)
      {
         return (GetRoleId(roleName) != -1);
      }
   }
}
