public void StartMigration(MigrationAccount Acct, MigrationOptions options, bool isServer = true,
        LogLevel logLevel = LogLevel.Info, bool isPreview = false, bool doRulesAndOOO = true)
        {
            string accountName = "";
            dynamic[] folders = null;
            int idx = Acct.AccountName.IndexOf("@");
            Log.Level level = (Log.Level)logLevel;
            dynamic user = null;
            string value = "";

            options.IsMaintainenceMode = false;

            if (MailClient == "MAPI")
            {
            user = new MapiUser();
            }
            if (!isServer)
            {
            m_umUser = user;
            }
            if (idx == -1)
            {
            Acct.LastProblemInfo = new ProblemInfo(Acct.AccountName, "Illegal account name",
                ProblemInfo.TYPE_ERR);
            Acct.TotalErrors++;
            return;
            }
            else
            {
            accountName = Acct.AccountName.Substring(0, idx);
            }

            Log.init(Path.GetTempPath() + "migration.log", level);  // might have gotten a new level from options
            InitLogFile(accountName, level);
            try
            {
            value = user.Init(isServer ? "host" : "", Acct.AccountID, accountName);
            }
            catch (Exception e)
            {
            string s = string.Format("Initialization Exception. {0}", e.Message);

            Acct.LastProblemInfo = new ProblemInfo(accountName, s, ProblemInfo.TYPE_ERR);
            Acct.TotalErrors++;
            return;
            }
            Log.info("Account name", accountName);
            Log.info("Account Id", Acct.AccountID);
            Log.info("Account Num", Acct.AccountNum.ToString());

            if (value.Length > 0)
            {
            Acct.IsValid = false;
            Log.err("Unable to initialize", accountName, value +"or verify if source mailbox exists.");
            Acct.LastProblemInfo = new ProblemInfo(accountName, value + " Or Verify if source mailbox exists.", ProblemInfo.TYPE_ERR);
            Acct.TotalErrors++;
            //Acct.TotalErrors = Acct.MaxErrorCount;
            return;
            }
            else
            {
            Acct.IsValid = true;
            Log.info(accountName, "initialized");
            }

            // set up check for skipping folders
            List<string> skipList = new List<string>();

            if (options.SkipFolders != null && options.SkipFolders.Length > 0)
            {
            string[] tokens = options.SkipFolders.Split(',');

            for (int i = 0; i < tokens.Length; i++)
            {
                string token = tokens.GetValue(i).ToString();

                skipList.Add(token.Trim());
            }
            }

            Log.debug("Retrieving folders");
            try
            {

            folders = user.GetFolders();
            }
            catch (Exception e)
            {
            Log.err("exception in startmigration->user.GetFolders", e.Message);

            }
            if (folders != null)
            {
            Log.info("CSmigrationwrapper get folders returned folders");
            if (folders.Count() == 0)
            {

                Log.info("No folders for user to migrate");
                return;
            }
            }
            else
            {
            Log.err("CSmigrationwrapper get folders returned null for folders");
            return;
            }
            Acct.migrationFolder.CurrentCountOfItems = folders.Count();
            Log.debug("Retrieved folders.  Count:", Acct.migrationFolder.CurrentCountOfItems.ToString());

            foreach (dynamic folder in folders) {
            if (!SkipFolder(options, skipList, folder))
                Acct.TotalItems += folder.ItemCount;
            }
            Log.info("Acct.TotalItems=", Acct.TotalItems.ToString());
            ZimbraAPI  api = new ZimbraAPI(isServer, logLevel, options.SpecialCharRep);

            api.AccountID = Acct.AccountID;
            api.AccountName = Acct.AccountName;

            api.GetTags();
            foreach (TagInfo taginfo in ZimbraValues.GetZimbraValues().Tags)
            {
            try
            {

                Acct.tagDict.Add(taginfo.TagName, taginfo.TagID);
            }
            catch (Exception e)
            {
                Log.err("Exception in Add tags :",e.Message);
            }
            }

            foreach (dynamic folder in folders)
            {
            string path = "";

            if (options.IsMaintainenceMode)
            {
                Log.err("Cancelling migration -- Mailbox is in maintainence  mode.try back later");
                return;
            }

            if (options.MaxErrorCnt > 0)
            {
                if (Acct.TotalErrors > options.MaxErrorCnt)
                {
                    Log.err("Cancelling migration -- error threshold reached");
                    return;
                }
            }

            if (SkipFolder(options, skipList, folder))
            {
                Log.info("Skipping folder", folder.Name);
                continue;
            }
            Log.info("Processing folder", folder.Name);
            if (folder.Id == 0)
            {
                string ViewType = GetFolderViewType(folder.ContainerClass);
                try
                {

                    int stat = api.CreateFolder(folder.FolderPath, ViewType);
                }
                catch (Exception e)
                {
                    Log.err("Exception in api.CreateFolder in Startmigration ", e.Message);
                }

                path = folder.FolderPath;
            }
            if (folder.ItemCount == 0)
            {
                Log.info("Skipping empty folder", folder.Name);
                continue;
            }
            // Set FolderName at the end, since we trigger results on that, so we need all the values set
            Acct.migrationFolder.TotalCountOfItems = folder.ItemCount;
            Acct.migrationFolder.CurrentCountOfItems = 0;
            Acct.migrationFolder.FolderView = folder.ContainerClass;
            Acct.migrationFolder.FolderName = folder.Name;
            if (folder.Id == (int)ZimbraFolders.Trash)
            {
                path = "/MAPIRoot/Deleted Items";   // FBS EXCHANGE SPECIFIC HACK !!!
            }
            if (!isPreview)
            {
                ProcessItems(Acct, isServer, user, folder, api, path, options);
            }
            }

            // now do Rules
            if ((options.ItemsAndFolders.HasFlag(ItemsAndFoldersOptions.Rules)) && (doRulesAndOOO))
            {
            string[,] data  = null;
            try
            {
                data = user.GetRules();
            }
            catch (Exception e)
            {
                Log.err("Exception in StartMigration->user.Getrules", e.Message);
            }
            if (data != null)
            {
                Acct.TotalItems++;
                Acct.migrationFolder.TotalCountOfItems = 1;
                Acct.migrationFolder.CurrentCountOfItems = 0;
                Acct.migrationFolder.FolderView = "All Rules";
                Acct.migrationFolder.FolderName = "Rules Table";
                api.AccountID = Acct.AccountID;
                api.AccountName = Acct.AccountName;
                if (!isPreview)
                {
                    Dictionary<string, string> dict = new Dictionary<string, string>();
                    int bound0 = data.GetUpperBound(0);
                    if (bound0 > 0)
                    {
                        for (int i = 0; i <= bound0; i++)
                        {
                            string Key = data[0, i];
                            string Value = data[1, i];
                            try
                            {

                                dict.Add(Key, Value);
                            }
                            catch (Exception e)
                            {
                                string s = string.Format("Exception adding {0}/{1}: {2}", Key, Value, e.Message);
                                Log.warn(s);
                                // Console.WriteLine("{0}, {1}", so1, so2);
                            }
                        }
                    }
                        api.AccountID = Acct.AccountID;
                        api.AccountName = Acct.AccountName;
                        try
                        {
                            Log.info("Migrating Rules");
                            int stat = api.AddRules(dict);
                        }
                        catch (Exception e)
                        {
                            Acct.TotalErrors++;
                            Log.err("CSmigrationWrapper: Exception in AddRules ", e.Message);

                        }
                        Acct.migrationFolder.CurrentCountOfItems = 1;
                    }

            }
            else
            {
                Log.info("There are no rules to migrate");
            }
            }

            // now do OOO
            if ((options.ItemsAndFolders.HasFlag(ItemsAndFoldersOptions.OOO)) && (doRulesAndOOO))
            {
            bool isOOO = false;
            string ooo ="";
            try
            {
                ooo = user.GetOOO();
            }
            catch (Exception e)
            {
                Log.err("Exception in StartMigration->user.GetOOO", e.Message);
            }
            if (ooo.Length > 0)
            {
                isOOO = (ooo != "0:");
            }
            if (isOOO)
            {
                Acct.TotalItems++;
                Acct.migrationFolder.TotalCountOfItems = 1;
                Acct.migrationFolder.CurrentCountOfItems = 0;
                Acct.migrationFolder.FolderView = "OOO";
                Acct.migrationFolder.FolderName = "Out of Office";
                api.AccountID = Acct.AccountID;
                api.AccountName = Acct.AccountName;
                if (!isPreview)
                {
                    Log.info("Migrating Out of Office");
                    try
                    {

                        api.AddOOO(ooo, isServer);
                    }
                    catch (Exception e)
                    {
                        Acct.TotalErrors++;
                        Log.err("CSmigrationWrapper: Exception in AddOOO ", e.Message);
                    }
                }
            }
            else
            {
                Log.info("Out of Office state is off, and there is no message");
            }
            }
            try
            {
            user.Uninit();
            }
            catch (Exception e)
            {
            Log.err("Exception in user.Uninit ", e.Message);

            }
            if (!isServer)
            {
            m_umUser = null;
            }
        }