// ========================================================================
// Copyright 2006 - Volian Enterprises, Inc. All rights reserved.          
// Volian Enterprises - Proprietary Information - DO NOT COPY OR DISTRIBUTE
// ------------------------------------------------------------------------
// $Workfile: $     $Revision: $                                           
// $Author: $   $Date: $                                                   
//                                                                         
// $History: $                                                             
// ========================================================================
using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Windows.Forms;
using System.Text;
using VEPROMS.CSLA.Library;
using Config;
namespace DataLoader
{
	/// 
	/// Summary description for Security.
	/// 
    /// 
    #region OldVeSamClasses
    // do a temp plant - we may keep this for loading in data. It will be migrated
    // to a folders record.
    #region Options
    public class PlantOptions
    {
        private UInt16 _id;
        private UInt32 _plopts;
        public List poList = new List();
        
        public UInt16 Id
        {
            get {return _id;}
            set {if (_id != value) _id = value;}
        }
        public UInt32 Options
        {
            get {return _plopts;}
            set {if (_plopts != value) _plopts = value;}
        }
    }
    public class ProcOptions
    {
        private UInt16 _id;
        private UInt16 _selected;
        public UInt32 [] Options = new UInt32[4];
        
        public UInt16 Id
        {
            get {return _id;}
            set {if (_id != value)_id = value;}
        }
        public UInt16 Selected
        {
            get {return _selected;}
            set {if (_selected != value)_selected = value;}
        }
    }
    #endregion
    #region OldFolders
    public class Plant
    {
        private string _name;
        private string _path;
        private UInt16 _id;
        public Dictionary psDic = new Dictionary();
        public string Name
        {
            get {return _name;}
            set 
            {
                if (value == null) value = string.Empty;
                if (_name != value) _name = value;
            }
        }
        public string Path
        {
            get {return _path;}
            set
            {
                if (value == null) value = string.Empty;
                if (_path != value)_path = value;
            }
        }
        public UInt16 Id
        {
            get {return _id;}
            set {if (_id != value) _id = value;}
        }
        public Plant() { }
        public Plant(string nm, string pth, UInt16 idn)
        {
            _name = nm;
            _path = pth;
            _id = idn;
        }
    }
    public class ProcSet
    {
        private string _name;
        private string _path;
        private UInt16 _id;
        public string Name
        {
            get {return _name;}
            set
            {
                if (value == null) value = string.Empty;
                if (_name != value)_name = value;
            }
        }
        public string Path
        {
            get {return _path;}
            set
            {
                if (value == null) value = string.Empty;
                if (_path != value)_path = value;
            }
        }
        public UInt16 Id
        {
            get {return _id;}
            set {if (_id != value) _id = value;}
        }
        public ProcSet() { }
        public ProcSet(string nm, string pth, UInt16 idn)
        {
            _name = nm;
            _path = pth;
            _id = idn;
        }
    }
    #endregion
    #region OldUser
    // The OldUser class stores data from the vesam input. The User class migrates
    // and saves data to the new sql database.
    public class OldUser
    {
        private UInt32 _systemopts;
        private string _username;
        private bool _blockaccessflag = false;
        public List PlantOpts = new List();
        public UInt32 SystemOpts
        {
            get { return _systemopts; }
            set { if (_systemopts != value) _systemopts = value; }
        }
        public string UserName
        {
            get { return _username; }
            set
            {
                if (value == null) value = string.Empty;
                if (_username != value) _username = value;
            }
        }
       
        public bool BlockAccessFlag
        {
            get { return _blockaccessflag; }
            set { if (_blockaccessflag != value) _blockaccessflag = value; }
        }
 
        public bool PermissionToManageFlag
        {
            get { return (_systemopts & VESamOpt.DOCMAINT)==0?false:true; }
            //set { if (_permissiontomanageflag != value) _permissiontomanageflag = value; }
        }
        public bool SystemAdminFlag
        {
            get { return (_systemopts & VESamOpt.SYSADMIN)==0 ? false:true; }
            //set { if (_systemadminflag != value) _systemadminflag = value; }
        }
        public bool PermissionToLockFlag
        {
            get { return (_systemopts & VESamOpt.LOCKSYSTEM)==0 ? false:true; }
            //set { if (_permissiontolockflag != value) _permissiontolockflag = value; }
        }
        public bool RoEditorFlag
        {
            get { return (_systemopts & VESamOpt.ROEDITOR) == 0 ? false : true; }
        }
 
        public OldUser(string nm)
        {
            _username = nm;
        }
    }
    #endregion
    #region VESam
    public class VESamOpt
    {
        #region Log4Net
        private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
        #endregion
        public const long VIEW = 0x00000001L;
        public const long PRINT = 0x00000002L;
        public const long PRINTDRAFT = 0x00000004L;
        public const long PRINTCHANGES = 0x00000008L;
        public const long EDIT = 0x00000010L;
        public const long SEARCH = 0x00000020L;
        public const long STANDARDSTEPS = 0x00000040L;
        public const long APPROVE = 0x00000080L;
        public const long APPROVESINGLE = 0x00000100L;
        public const long LIBRARYDOCS = 0x00000200L;
        public const long ADDMODDEL = 0x00000400L;
        public const long CLEAN = 0x00000800L;
        public const long LOCKPROC = 0x00001000L;
        public const long LOCKSET = 0x00000001L;
        public const long UCF = 0x00000002L;
        public const long LOCKSYSTEM = 0x00000001L;
        public const long DOCMAINT = 0x00000002L;
        public const long ROEDITOR = 0x00000004L;
        public const long SYSADMIN = 0x00000008L;
        public const int SUPERUSER = 1000;
        public const long SUPERACCESS = 0xFFFFFFFFL;
        private bool _blockAccess;
        public int userid = -1;
        public string initials;
        private const string samoptname = "vesam.opt"; 
        public FileStream fs;
        public BinaryReader bw;
        public bool isDemoMode = false;
        List plntList = new List();
        List userList = new List();
        Dictionary plntDic = new Dictionary();
        public bool BlockAccess
        {
            get { return _blockAccess; }
            set { if (_blockAccess != value) _blockAccess = value; }
        }
        public bool OpenFile(string oname)
        {
            try
            {
                fs = new FileStream(oname, FileMode.Open, FileAccess.Read, FileShare.Read, 1, false);
                bw = new BinaryReader(fs);
                return true;
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message, "Security File");
                return false;
            }
        }
        public void CloseFile()
        {
            bw.Close();
            fs.Close();
            bw = null;
            fs = null;
        }
        public Dictionary LoadPlants()
        {
            UInt16 ui16;
            UInt32 ui32;
            try
            {
                byte x;
                // read past some header stuff.
                for (int jj = 0; jj < 8; jj++) x = bw.ReadByte();
                long nxtPl = bw.ReadUInt32();
                uint nmPlant = bw.ReadUInt16();
                ui16 = bw.ReadUInt16();
                // not needed here, but need to read past this...
                long nxtUs = bw.ReadUInt32();
                uint nmUser = bw.ReadUInt16();
                ui16 = bw.ReadUInt16();
                long nxtGr = bw.ReadUInt32();
                uint nmGrp = bw.ReadUInt16();
                ui16 = bw.ReadUInt16();
                BlockAccess = bw.ReadUInt16()==0?false:true;
                string pname, ppth;
                for (int i = 0; i < nmPlant; i++)
                {
                    if (nxtPl == 0xFFFFFFFEL)
                    {
                        log.Error("Reading in VESAM options file - cannot find next plant in list");
                        break;
                    }
                    fs.Seek(nxtPl, SeekOrigin.Begin);
                    nxtPl = bw.ReadUInt32();
                    Plant pl = new Plant();
                    pl.Id = bw.ReadUInt16();
                    ui16 = bw.ReadUInt16();
                    byte[] stmp = new byte[256];
                    stmp = bw.ReadBytes(ui16);
                    pname = Encoding.ASCII.GetString(stmp, 0, ui16);
                    pl.Name = pname;
                    ui16 = bw.ReadUInt16();
                    stmp = bw.ReadBytes(ui16);
                    ppth = Encoding.ASCII.GetString(stmp, 0, ui16);
                    pl.Path = ppth;
                    // read in any sets within this plant.
                    UInt16 nmPrcDr = bw.ReadUInt16();
                    ui32 = bw.ReadUInt32();
                    UInt32 nxtPr = bw.ReadUInt32();
                    for (int j = 0; j < nmPrcDr; j++)
                    {
                        ProcSet ps = new ProcSet();
                        ps.Id = bw.ReadUInt16();
                        ui16 = bw.ReadUInt16();
                        stmp = bw.ReadBytes(ui16);
                        pname = Encoding.ASCII.GetString(stmp, 0, ui16);
                        ps.Name = pname;
                        ui16 = bw.ReadUInt16();
                        stmp = bw.ReadBytes(ui16);
                        ppth = Encoding.ASCII.GetString(stmp, 0, ui16);
                        ps.Path = ppth;
                        ui32 = bw.ReadUInt32();
                        if (nxtPr == 0xFFFFFFFDL && j + 1 < nmPrcDr)
                        {
                            log.ErrorFormat("Loading vesam.opt - procedure sets for {0}", ps.Name);
                            return null;
                        }
                        try
                        {
                            pl.psDic.Add(ps.Id, ps);
                        }
                        catch (Exception ex)
                        {
                            log.ErrorFormat("Adding to set dictionary - {0}. Error: {1}" + ps.Path, ex.Message);
                        }
                        if (nxtPr != 0xFFFFFFFDL)
                        {
                            fs.Seek(nxtPr, SeekOrigin.Begin);
                            nxtPr = bw.ReadUInt32();
                        }
                    }
                    try
                    {
                        if (!plntDic.ContainsKey(pl.Id))plntDic.Add(pl.Id, pl);
                    }
                    catch (Exception ex)
                    {
                        log.ErrorFormat("Adding to plant dictionary - {0}. Error: {1}", pl.Path, ex.Message);
                    }
                }
            }
            catch (Exception ex)
            {
                log.ErrorFormat("Loading plants from vesam.opt: {0}", ex.Message);
                return null;
            }
            return plntDic;
        }
        public List LoadUserList()
        {
            UInt16 ui16;
            UInt32 ui32;
            try
            {
                byte x;
                fs.Seek(0, SeekOrigin.Begin);
                // read past some header stuff.
                for (int jj = 0; jj < 8; jj++) x = bw.ReadByte();
                long nxtPl = bw.ReadUInt32();
                uint nmPlant = bw.ReadUInt16();
                ui16 = bw.ReadUInt16();
                // get info in header for users
                long nxtUs = bw.ReadUInt32();
                uint nmUser = bw.ReadUInt16();
                ui16 = bw.ReadUInt16();
                long nxtGr = bw.ReadUInt32();
                uint nmGrp = bw.ReadUInt16();
                ui16 = bw.ReadUInt16();
                bool localblockAccess = bw.ReadUInt16()==0?false:true;
                // Now read in all of the user information
                UInt16 uid;
                string fName, fPass;
                for (int i = 0; i < nmUser; i++)
                {
                    if (nxtUs == 0xFFFFFFFCL && i + 1 < nmUser)
                    {
                        log.Error("Loading vesam.opt - reading in user list.");
                        return null;
                    }
                    fs.Seek((long)nxtUs, SeekOrigin.Begin);
                    nxtUs = bw.ReadUInt32();
                    uid = bw.ReadUInt16();
                    ui16 = bw.ReadUInt16();  // user's group?
                    byte[] test = new byte[10];
                    test = bw.ReadBytes(10);
                    // get ve-proms (vesam) username & password
                    fName = Encoding.ASCII.GetString(test, 0, 10);
                    int indx = fName.IndexOf("\0");
                    string fNameTrim = fName.Substring(0, indx);
                    test = bw.ReadBytes(10);
                    fPass = Encoding.ASCII.GetString(test, 0, 10);
                    indx = fPass.IndexOf("\0");
                    string fPassTrim = fPass.Substring(0, indx);
                    OldUser usr = new OldUser(fNameTrim);
                    usr.SystemOpts = bw.ReadUInt32();
                    usr.BlockAccessFlag = localblockAccess;
                    ui32 = bw.ReadUInt32();
                    // now get plant & proc set options.
                    nmPlant = bw.ReadUInt16();
                    for (int j = 0; j < nmPlant; j++)
                    {
                        PlantOptions plO = new PlantOptions();
                        plO.Id = bw.ReadUInt16();
                        plO.Options = bw.ReadUInt32();
                        ui32 = bw.ReadUInt32();
                        UInt16 nmPrcDr = bw.ReadUInt16();
                        for (int k = 0; k < nmPrcDr; k++)
                        {
                            ProcOptions prO = new ProcOptions();
                            prO.Id = bw.ReadUInt16();
                            prO.Selected = bw.ReadUInt16();
                            for (int kk = 0; kk < 4; kk++) prO.Options[kk] = bw.ReadUInt32();
                            plO.poList.Add(prO);
                        }
                        usr.PlantOpts.Add(plO);
                    }
                    userList.Add(usr);
                }
            }
            catch (Exception ex)
            {
                log.ErrorFormat("Error Loading (old) User info from vesam.opt: {0}", ex.Message);
                return null ;
            }
            return userList;
        }
    }
    #endregion
    #endregion
    #region SecurityMigration
    public class Security
    {
        #region Log4Net
        private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
        #endregion
        Dictionary plntDic = new Dictionary();
        List userList = new List();
		private string _VePromsPath = null;
        private string optfilename;
        private string[] prflags ={ "Vfw", "Prnt", "Prnt Drft", "Prnt Chgs", "Edit", "Srch", "St Stp", "App", "App Sel", "Lib", "AMD", "Clean", "Lock" };
        private string[] sysflags ={ "NetworkLock", "SysMaint", "ROEditor", "SysAdmin" };
        #region NewMig
        public Security(string pathname, string vepromspath)
        {
            if (File.Exists(pathname) == false)
            {
                MessageBox.Show("Could not locate the Security Options file:\n\n" + pathname, "Security Access Error");
                optfilename = null;
                return;
            }
			_VePromsPath = vepromspath;
            optfilename = pathname;
        }
        public bool Migrate()
        {
            VESamOpt vso = new VESamOpt();
            bool suc = vso.OpenFile(optfilename);
            if (!suc) return false;
            plntDic = vso.LoadPlants();
            if (plntDic == null) return false;
            suc = VerifyFolders(plntDic);
            if (!suc) return suc;
            userList = vso.LoadUserList();
            if (userList == null) return false;
            vso.CloseFile();
            vso = null;
            log.Info("Original vesam.opt loaded successfully - next step is to migrate security information to new database");
            //WriteOutSummary(plntDic, userList);
            suc = TranslateToNew(vso, plntDic, userList);
            log.Info("Migrated vesam successfully");
            return suc ;
        }
        #endregion
        #region WriteVESamSummary
        private void WriteOutSummary(Dictionary plntDic, List userList)
        {
            foreach (OldUser usr in userList)
            {
                log.InfoFormat("User = {0}", usr.UserName);
                StringBuilder sb = new StringBuilder();
                for (int i = 0; i < 4; i++)
                {
                    if ((usr.SystemOpts & (1L << i)) != 0) sb.Append(sysflags[i] + " ");
                }
                if (sb.Length > 0) log.InfoFormat(" System Options = {0}", sb.ToString());
                // for now, don't worry about system options.
                // for each plant, list any permissions of the plant or its proc sets. If 
                // none set, nothing will be listed.
                foreach (PlantOptions po in usr.PlantOpts)
                {
                    bool plntout = false;
                    Plant pl = (Plant)plntDic[po.Id];
                    if (po.Options != 0)
                    {
                        plntout = true;
                        log.InfoFormat(" Plant = {0}. Options = {1}", pl.Name, po.Options);
                    }
                    foreach (ProcOptions psO in po.poList)
                    {
                        ProcSet ps = (ProcSet)pl.psDic[psO.Id];
                        if (psO.Options[0] != 0 || psO.Options[1] != 0 || psO.Options[2] != 0 || psO.Options[3] != 0)
                        {
                            if (!plntout) log.InfoFormat(" Plant = {0}.", pl.Name);
                            log.InfoFormat("  Procedure Set = {0}", ps.Name);
                            sb.Length = 0;
                            int nm = 0;
                            for (int i1 = 0; i1 < 4; i1++)
                            {
                                for (int j1 = 0; j1 < 16; j1++)
                                {
                                    if ((psO.Options[i1] & (1L << j1)) != 0) sb.Append(prflags[nm] + " ");
                                    nm++;
                                }
                            }
                            if (sb.Length > 0) log.InfoFormat("   {0}", sb.ToString());
                        }
                    }
                }
            }
        }
        #endregion
        #region MigrateCode
        private string[] defaultRole ={ "Administrator", "User Administrator", "RO Manager", "Writer", "Reviewer", "Guest" };
        private string[] defaultRoleTitle = { "Manages Data - Backups, Approval etc.", "Maintains User Security", "Maintains Referenced Objects", "Can Edit", "Can potentially add comments", "Read-Only access to approved procedures" };
        // defaultPermData sets the permission data (Permissions table) - columns are
        // PermLevel, VersionType, PermValue (Note for vesam migration, PermAD is always allow, i.e. 0)
        private int[,] defaultPermData = {
            {2, 3, 15},     // Administrator
            {1, 3, 15},     // User Administrator
            {3, 3, 15},     // RO Manager
            {5, 1, 15},     // Writer
            {7, 3, 15},     // Reviewer
            {2, 2, 1}};     // Guest
        private int[] accessLevelSetup = { -1, 5, 4, 3, 0, 0, 2, 1 };
        private int[] accessLevelTrans;
        private Dictionary AddDefaultRoles()
        {
            Dictionary rdic = new Dictionary();
            try
            {
                accessLevelTrans = new int[accessLevelSetup.Length];
                for (int i = 0; i < 6; i++)
                {
                    Role role = Role.New();
                    role.Name = defaultRole[i];
                    role.Title = defaultRoleTitle[i];
					if (!role.IsSavable) ErrorRpt.ErrorReport(role);
					role.Save();
                    Permission perm = Permission.New();
                    perm.MyRole = role;
                    perm.PermLevel = defaultPermData[i, 0];
                    perm.VersionType = defaultPermData[i, 1];
                    perm.PermValue = defaultPermData[i, 2];
					if (!perm.IsSavable) ErrorRpt.ErrorReport(perm);
					perm.Save();
                    rdic.Add(role.RID, role);
                    for (int j = 1; j < accessLevelSetup.Length; j++)
                    {
                        if (accessLevelSetup[j] == i) accessLevelTrans[j] = role.RID;
                    }
                }
                  
            }
            catch (Exception ex)
            {
                log.ErrorFormat("Error setting default roles & permissions: {0}", ex.Message);
                return null;
            }
            return rdic;
        }
        public bool VerifyFolders(Dictionary dicPlants)
        {
            try
            {
                // For each folder from vesam, see if there is a matching folder already
                // migrated...
                FolderInfoList fil = FolderInfoList.Get();
                // add the titles to a dictionary for quick checking
                List folderlist = new List();
                foreach (FolderInfo fi in fil)
                {
                    folderlist.Add(fi.Title.ToUpper());
                }
                foreach (ushort u in dicPlants.Keys)
                {
                    Plant pl = dicPlants[u];
                    bool foundplant = false;
                    if (folderlist.Contains(pl.Path.ToUpper())) foundplant=true;
                   
                    if (!foundplant)
                       log.InfoFormat("Plant from vesam.opt not found in folder data: {0}", pl.Path);
                    else  // if found, check for sets
                    {
                        foreach (ushort uu in pl.psDic.Keys)
                        {
                            ProcSet pr = pl.psDic[uu];
                            bool foundprocset = false;
                            foreach (FolderInfo fi in fil)
                            {
                                string tstpath = pl.Path.ToUpper() + "\\" + pr.Path.ToUpper();
                                if (tstpath == fi.Title.ToUpper())
                                {
                                    foundprocset = true;
                                    break;
                                }
                            }
                            if (!foundprocset) log.InfoFormat("Procedure Set from vesam.opt not found in folder data: {0}\\{1}", pl.Path, pr.Path);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                log.ErrorFormat("error mapping vesam directories to data directories, error = {0}", ex.Message);
                return false;
            }
            return true;
        }
        private Dictionary LoadFolders()
        {
            FolderInfoList fldlist = FolderInfoList.Get();
            Dictionary fdic = new Dictionary();
            foreach (FolderInfo fi in fldlist)
            {
                fdic.Add(fi.Title.ToUpper(), fi.FolderID);
            }
            return fdic;
        }
        private bool TranslateToNew(VESamOpt vso, Dictionary plntDic, List userList)
        {
            Dictionary rlpdic = AddDefaultRoles();
            AddUsrGrpAsgnRecs(plntDic, userList);
            return true;
        }
        private string VersionName(string s)
        {
            return s.Substring(s.LastIndexOf(" - ") + 3);
        }
        private string SetName(string s)
        {
            return s.Substring(0, s.LastIndexOf(" - "));
        }
        private string FixName(string s)
        {
            s = s.Replace(" - Working Draft (Unit 1)", " (Unit 1) - Working Draft");
            s = s.Replace(" - Working Draft (Unit 2)", " (Unit 2) - Working Draft");
            s = s.Replace(" - Current Approved Version", " - Approved Version");
            return s.Replace(" -  Working Draft", " - Working Draft");
        }
        private int CalcAccessLevel(int iBase, uint options, string sVersion)
        {
            if (sVersion == "Working Draft")
            {
                if (options == 0) return 0;
                if ((options & 6528) != 0) return 5;
                if ((options & 1024) != 0) return 4;
                if ((options & 528) != 0) return 3;
                return 2;
            }
            else
            {
                if (iBase != 0) return iBase;
                else if (options != 0) return 1;
                return 0;
            }
        }
        private string SystemOption(uint options)
        {
            if ((options & 11) != 0) return "\"Admin\"";
            if (options == 4) return "\"RO\"";
            return "";
        }
        private void AddAccessRights(Dictionary> dic, int folderId, int roleId)
        {
            if (!dic.ContainsKey(folderId)) dic[folderId] = new List();
            dic[folderId].Add(roleId);
        }
        private void AddUsrGrpAsgnRecs(Dictionary plntDic, List userList)
        {
            Dictionary> dicGroups = new Dictionary>();
            Dictionary dicGroupIds = new Dictionary();
            Dictionary dicOldFolders = new Dictionary();
            int oldFolderCount = 1;
            dicOldFolders.Add("system", oldFolderCount++);
            Dictionary dicNewFolders = LoadFolders();
            List lstVersions = new List();
            StringBuilder sb;
            OldUser frst = userList[0];
            string[] accessLevel = { "", "\"Guest\"", "\"Reviewer\"", "\"Writer\"", "\"Admin\"", "\"Admin\"" };
            foreach (OldUser usr in userList)
            {
                int sysAccess = 5;
                Dictionary plantAccess = new Dictionary();
                if ((usr.SystemOpts & 11) == 0)
                {
                    foreach (PlantOptions po in usr.PlantOpts)
                    {
                        plantAccess[po] = 5;
                        Plant pl = (Plant)plntDic[po.Id];
                        if (!dicOldFolders.ContainsKey(pl.Path.ToUpper()))dicOldFolders.Add(pl.Path.ToUpper(), oldFolderCount++);
                        string sSetLast = "";
                        int iAccessLevel = 0;
                        foreach (ProcOptions psO in po.poList)
                        {
                            ProcSet ps = null;
                            try
                            {
                                ps = (ProcSet)pl.psDic[psO.Id];
                            }
                            catch (Exception ex)
                            {
                                MessageBox.Show("here: " + ex.Message);
                            }
                            if (!dicOldFolders.ContainsKey(pl.Path.ToUpper()+"\\"+ps.Path.ToUpper()))dicOldFolders.Add(pl.Path.ToUpper()+"\\"+ps.Path.ToUpper(), oldFolderCount++);
                            string sName = FixName(ps.Name);
                            string sVersion = VersionName(sName);
                            string sSet = SetName(sName);
                            if (sSet != sSetLast)
                            {
                                if (sSetLast != "")
                                {
                                    // if the proc access is lower than the plant, reset plant level.
                                    if (iAccessLevel < plantAccess[po]) plantAccess[po] = iAccessLevel;
                                    iAccessLevel = 0;
                                }
                                sSetLast = sSet;
                            }
                            iAccessLevel = CalcAccessLevel(iAccessLevel, psO.Options[0], sVersion);
                        }
                        // do one last check to see if plant level should be lowered. Also
                        // check if the system level should be lowered.
                        if (iAccessLevel < plantAccess[po]) plantAccess[po] = iAccessLevel;
                        if (plantAccess[po] < sysAccess) sysAccess = plantAccess[po];
                    }
                }
                // set the system level access, i.e. User Admin, System Admin & RO Editor roles if
                // necessary.
                int systemid = dicOldFolders["system"];
                Dictionary> accessRights = new Dictionary>();
                if (usr.SystemOpts != 0) AddAccessRights(accessRights, systemid, accessLevelTrans[6]);  // add ro editor
                if ((usr.SystemOpts & 11) != 0)
                {
                    AddAccessRights(accessRights, systemid, accessLevelTrans[5]);  // add sys admin rights
                    AddAccessRights(accessRights, systemid, accessLevelTrans[7]);  // and add user admin rights
                }
                else
                {
                    // the user has a role at the system level that is not an admin, 
                    // such as reviewer or guest - add it in.
                    if (sysAccess > 0) AddAccessRights(accessRights, systemid, accessLevelTrans[sysAccess]);
                }
                sb = new StringBuilder(string.Format("{0},{1}", (usr.SystemOpts == 0 ? "" : "Admin"), accessLevel[sysAccess]));
                if ((usr.SystemOpts & 11) == 0)
                {
                    foreach (PlantOptions po in usr.PlantOpts)
                    {
                        Plant pl = plntDic[po.Id];
                        // Need logic for po.Options in combination with PlantAccess[po]
                        //sb.Append(string.Format(",{0}", po.Options));
                        
                        if (plantAccess[po] > sysAccess)
                        {
                            AddAccessRights(accessRights, dicOldFolders[pl.Path.ToUpper()], accessLevelTrans[plantAccess[po]]);
                            sb.Append(string.Format(",{0}", accessLevel[plantAccess[po]]));
                        }
                        else
                            sb.Append(",");
                        string sSetLast = "";
                        string sPathLast = "";
                        int iAccessLevel = 0;
                        string sPath = "";
                        foreach (ProcOptions psO in po.poList)
                        {
                            ProcSet ps = pl.psDic[psO.Id];
                            string sName = FixName(ps.Name);
                            string sVersion = VersionName(sName);
                            if (sVersion == "Working Draft") sPath = pl.Path + "\\" + ps.Path;
                            string sSet = SetName(sName);
                            if (sSet != sSetLast)
                            {
                                if (sSetLast != "")
                                {
                                    if (iAccessLevel > plantAccess[po])
                                    {
                                        AddAccessRights(accessRights, dicOldFolders[sPathLast.ToUpper()], accessLevelTrans[iAccessLevel]);
                                        sb.Append(string.Format(",{0}", accessLevel[iAccessLevel]));
                                    }
                                    else
                                        sb.Append(",");
                                    iAccessLevel = 0;
                                }
                                sSetLast = sSet;
                                sPathLast = sPath;
                            }
                            iAccessLevel = CalcAccessLevel(iAccessLevel, psO.Options[0], sVersion);
                        }
                        if (iAccessLevel > plantAccess[po])
                        {
                            AddAccessRights(accessRights, dicOldFolders[sPathLast.ToUpper()], accessLevelTrans[iAccessLevel]);
                            sb.Append(string.Format(",{0}", accessLevel[iAccessLevel]));
                        }
                        else
                            sb.Append(",");
                    }   
                }
                string s = sb.ToString();
                if (!dicGroups.ContainsKey(s))
                {
                    dicGroups[s] = new List();
                    Group grp = Group.New();
                    grp.GroupName = "Group " + dicGroups.Count.ToString();
                    int pathInData = -1;
                    foreach (int folderId in accessRights.Keys)
                    {
                        // see if this folderId exists in the data (rather
                        // than the list from vesam). If not, don't do an
                        // assignments record
                        pathInData = 0;
                        foreach (KeyValuePair kvp in dicOldFolders)
                        {
                            if (kvp.Value == folderId)
                            {
                                string path = kvp.Key;
                                if (dicNewFolders.ContainsKey(path.ToUpper()))
                                    pathInData = dicNewFolders[path.ToUpper()];
                            }
                        }
                        if (pathInData>0)
                        {
							if (!grp.IsSavable) ErrorRpt.ErrorReport(grp);
                            grp.Save();
                            Folder tmpfld = Folder.Get(pathInData);
                            foreach (int roleId in accessRights[folderId])
                            {
                                Role tmprole = Role.Get(roleId);
                                grp.GroupAssignments.Add(tmprole, tmpfld);
                            }
                        }
                    }
					if (!grp.IsSavable) ErrorRpt.ErrorReport(grp);
                    grp.Save();
                    dicGroupIds[s] = grp.GID;
                }
                dicGroups[s].Add(usr.UserName);
            }
            foreach (string s in dicGroups.Keys)
            {
                foreach (string sUser in dicGroups[s])
                {
                    // add user record & membership record.
                    User newusr = User.New();
                    newusr.UserID = sUser;
                    ConfigFile cfg = new ConfigFile();
                    cfg.LoadUsrCfg(newusr, _VePromsPath);
                    Group tmpgrp = Group.Get(dicGroupIds[s]);
                    newusr.UserMemberships.Add(tmpgrp);
					if (!newusr.IsSavable) ErrorRpt.ErrorReport(newusr);
					newusr.Save();
                }
            }
        }
        #endregion
    }
#endregion
}