public EditMigrationsWindow(EditMigrationsViewModel viewModel)
 {
     InitializeComponent();
     DataContext = viewModel;
 }
 public EditMigrationsWindow(EditMigrationsViewModel viewModel)
 {
     InitializeComponent();
     DataContext = viewModel;
 }
        /// <summary>
        /// Called when the Generate Migrations command is run
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param>
        private void MigrationsCallback(object sender, EventArgs e)
        {
            IntPtr hierarchyPtr, selectionContainerPtr;
            uint projectItemId;
            IVsMultiItemSelect mis;
            IVsMonitorSelection monitorSelection = (IVsMonitorSelection)GetGlobalService(typeof(SVsShellMonitorSelection));
            monitorSelection.GetCurrentSelection(out hierarchyPtr, out projectItemId, out mis, out selectionContainerPtr);

            IVsHierarchy hierarchy = Marshal.GetTypedObjectForIUnknown(hierarchyPtr, typeof(IVsHierarchy)) as IVsHierarchy;
            if (hierarchy == null)
            {
                FireError("F**k knows why but it is broken, sorry");
                return;
            }
            object projObj;
            hierarchy.GetProperty(projectItemId, (int)__VSHPROPID.VSHPROPID_ExtObject, out projObj);

            ProjectItem projItem = projObj as ProjectItem;

            if (projItem == null)
            {
                FireError("The item you have selected is not playing nicely. Apologies");
                return;
            }

            var project = projItem.ContainingProject;
            var migrations = new List<Migration>();

            var allClasses = GetProjectItems(project.ProjectItems).Where(v => v.Name.Contains(".cs"));
            // check for .cs extension on each,

            foreach (var c in allClasses)
            {
                var eles = c.FileCodeModel;
                if (eles == null)
                    continue;
                foreach (var ele in eles.CodeElements)
                {
                    if (ele is EnvDTE.CodeNamespace)
                    {
                        var ns = ele as EnvDTE.CodeNamespace;
                        // run through classes
                        foreach (var property in ns.Members)
                        {
                            var member = property as CodeType;
                            if (member == null)
                                continue;

                            // check all classes they derive from to see if any of them are migration classes, add them if so
                            migrations.AddRange(from object b in member.Bases select b as CodeClass into bClass where bClass != null && bClass.Name == "DataMigrationImpl" select new Migration(member));
                        }
                    }
                }
            }

            var model = projItem.FileCodeModel;
            if (model == null)
            {
                FireError("This class you have selected is weird and broken. Choose another one");
                return;
            }
            var elements = model.CodeElements;

            var classes = new List<Model>();

            // run through elements (they are done in a hierachy, so first we have using statements and the namespace) to find namespace
            foreach (var ele in elements)
            {
                if (ele is EnvDTE.CodeNamespace)
                {
                    var ns = ele as EnvDTE.CodeNamespace;
                    // run through classes
                    foreach (var c in ns.Members)
                    {
                        var member = c as CodeType;
                        if (member == null)
                            continue;

                        classes.Add(new Model() { Class = member, Name = member.Name });
                    }
                }
            }

            if (!classes.Any())
            {
                FireError("No classes in the selected file!");
                return;
            }

            var vm = new MigrationsViewModel(migrations, classes);
            var window = new MigrationsWindow(vm);
            var success = window.ShowDialog();

            if (!success.GetValueOrDefault())
            {
                return;
            }

            CodeType selectedClass = vm.SelectedClass.Class;

            if (selectedClass == null)
            {
                FireError("No class to generate migrations from!");
                return;
            }

            // name of class
            var modelName = selectedClass.Name;
            // get code class
            var cc = selectedClass as CodeClass;
            // get all members of the class
            var members = cc.Members;

            bool contentPartRecord = false;
            foreach (var d in cc.Bases)
            {
                var dClass = d as CodeClass;
                if (dClass != null && dClass.Name == "ContentPartRecord")
                {
                    contentPartRecord = true;
                }

            }

            var props = new List<MigrationItem>();

            //iterate through to find properties
            foreach (var member in members)
            {
                var prop = member as CodeProperty;
                if (prop == null)
                    continue;

                if (prop.Access != vsCMAccess.vsCMAccessPublic)
                    continue;

                var type = prop.Type;
                var name = prop.Name;
                var fullName = type.AsFullName;
                var nullable = fullName.Contains(".Nullable<");
                var sType = type.AsString.Replace("?", "");

                var sName = name;
                // if model, add _Id for nhibernate
                if (fullName.Contains(".Models.") || fullName.Contains(".Records."))
                {
                    sName += "_Id";
                    sType = "int";
                }

                var mi = new MigrationItem()
                {
                    Name = name,
                    SuggestedName = sName,
                    Type = fullName,
                    SuggestedType = sType,
                    Nullable = nullable,
                    Create = true,
                };

                props.Add(mi);
            }

            var createMigrationFile = !String.IsNullOrEmpty(vm.NewMigration);

            if (!createMigrationFile)
            {
                if (vm.SelectedMigration == null)
                {
                    FireError("Select a migration or choose a new one!");
                    return;
                }
                var mig = vm.SelectedMigration.CodeType;
                string path = (string)mig.ProjectItem.Properties.Item("FullPath").Value;
                string text = File.ReadAllText(path);

                var noTimesCreated = Regex.Matches(text, @"SchemaBuilder.Create\(""" + modelName + @""",").Count;
                var noTimesDropped = Regex.Matches(text, @"SchemaBuilder.DropTable\(""" + modelName + @"""\)").Count;
                bool created = noTimesCreated > noTimesDropped;

                if (noTimesCreated == 1 && noTimesDropped == 0)
                {
                    foreach (var p in props.Where(p => text.Contains(p.Name)))
                    {
                        p.Create = false;
                    }
                }

                if (created)
                {
                    foreach (var p in props)
                    {
                        var name = p.Name;
                        var noDrops = Regex.Matches(text, @".DropColumn\(""" + name).Count;
                        var noOccurences = Regex.Matches(text, name).Count;

                        if ((noOccurences - noDrops) > noDrops)
                            p.Create = false;
                    }
                }
            }

            // if a collection ignore
            foreach (var p in props) if (p.Type.Contains("System.Collection")) p.Create = false;

            var bmvm = new BuildMigrationsViewModel(props);
            var bmWindow = new BuildMigrationsWindow(bmvm);
            var bmSuccess = bmWindow.ShowDialog();

            if (!bmSuccess.GetValueOrDefault())
            {
                return;
            }

            var sb = new StringBuilder();
            var createTable = "SchemaBuilder.CreateTable(\"" + modelName + "\", t => t";
            sb.AppendLine(createTable);
            if (contentPartRecord) sb.AppendLine("\t.ContentPartRecord()");
            foreach (var p in bmvm.Migrations.Where(z => z.Create))
            {
                sb.AppendLine("\t" + ParseMigrationItem(p));
            }

            sb.AppendLine(");");

            var editViewModel = new EditMigrationsViewModel()
            {
                Migrations = sb.ToString()
            };

            var editWindow = new EditMigrationsWindow(editViewModel);
            var emSuccess = editWindow.ShowDialog();

            if (!emSuccess.GetValueOrDefault())
            {
                return;
            }

            var migrationsCode = new StringBuilder();
            using (StringReader reader = new StringReader(editViewModel.Migrations))
            {
                string line;
                while ((line = reader.ReadLine()) != null)
                {
                    migrationsCode.AppendLine(line.Insert(0, "\t\t\t"));
                }
            }

            if (!createMigrationFile)
                EditMigrations(vm.SelectedMigration.CodeType, migrationsCode.ToString());
            else
            {
                var templates = Path.Combine(Path.GetDirectoryName(GetType().Assembly.Location), "OrchardTemplates");
                var newMigration = project.ProjectItems.AddFromFileCopy(templates + "\\Migrationsxxx.cs");
                Insert(newMigration.Properties.Item("FullPath").Value.ToString(), new[]
                {
                    new KeyValuePair<string, string>("$module$", project.Name),
                    new KeyValuePair<string, string>("$migrationName$", vm.NewMigration),
                    new KeyValuePair<string, string>("$code$", migrationsCode.ToString())
                });

                var cs = vm.NewMigration.EndsWith(".cs") ? "" : ".cs";
                newMigration.Name = vm.NewMigration + cs;
            }
        }