using System;
using System.IO;
using System.Linq;
using System.Text;
using System.Data;
using System.Collections;
using System.Windows.Forms;
using System.Data.OleDb;
using Autodesk.Revit;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Mechanical;
using Autodesk.Revit.DB.Plumbing;
using Autodesk.Revit.DB.Electrical;
using Autodesk.Revit.UI;
using Autodesk.Revit.DB.Structure;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using TriangleNet;
using uBIMEarthTools.Utils;
using uBIMEarthTools.Model;

namespace uBIMEarthTools.Commands
{
    [Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
    public class GeologyCylinderCommand : IExternalCommand
    {
        public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
        {
            UIDocument uidoc = commandData.Application.ActiveUIDocument;
            Document doc = uidoc.Document;
            string pathstring;
            OpenFileDialog openFileDialog = new OpenFileDialog();
            openFileDialog.Title = "选择Excel文件…";
            openFileDialog.Filter = "文本文件|*.xls";
            openFileDialog.RestoreDirectory = false;
            openFileDialog.FilterIndex = 1;
            if (openFileDialog.ShowDialog() == DialogResult.OK)
                pathstring = openFileDialog.FileName;
            else
                return Result.Cancelled;

            List<Borehole> boreholeList = ExcelHelper.GetDataFromExcel(pathstring);
            List<string> typesList = ExcelHelper.GetGeologyType(pathstring).Select(x => "地质" + x.Item1 + "-" + x.Item2 + "层").ToList();

            TransactionStatus status = TransactionStatus.Uninitialized;
            TransactionGroup transGroup = new TransactionGroup(doc, "地质钻孔圆柱建模");
            if (transGroup.Start() == TransactionStatus.Started)
            {
                Transaction transaction = new Transaction(doc);
                FailureHandlingOptions failureHandlingOptions = transaction.GetFailureHandlingOptions();
                FailureHandler failureHandler = new FailureHandler();
                failureHandlingOptions.SetFailuresPreprocessor(failureHandler);
                failureHandlingOptions.SetClearAfterRollback(true);
                transaction.SetFailureHandlingOptions(failureHandlingOptions);


                #region 加载族,创建族类型
                IEnumerable<Element> familys = new FilteredElementCollector(doc)
                    .OfCategory(BuiltInCategory.OST_GenericModel)
                    .OfClass(typeof(FamilySymbol)).Where(x => x.Name == "地质钻孔圆柱");
                if (!familys.Any())
                {
                    transaction.Start("Load Family");
                    byte[] bit = Resource.地质钻孔圆柱 as byte[];
                    string filepath = AppConfig.APP_TEMP_PATH + "\\地质钻孔圆柱.rfa";
                    File.WriteAllBytes(filepath, bit);
                    doc.LoadFamily(filepath);
                    File.Delete(filepath);
                    transaction.Commit();
                }

                Family family = (new FilteredElementCollector(doc)
                    .OfCategory(BuiltInCategory.OST_GenericModel).OfClass(typeof(FamilySymbol))
                    .Where(x => x.Name == "地质钻孔圆柱").First() as FamilySymbol).Family;
                Document fdoc = doc.EditFamily(family);
                Transaction trans = new Transaction(fdoc);
                trans.Start("Create FamilySymbol");
                if (null != fdoc)
                {
                    FamilyManager fm = fdoc.FamilyManager;
                    foreach (string type in typesList)
                    {
                        try
                        {
                            FamilyType ft = fm.NewType(type);
                        }
                        catch
                        {
                        }
                    }

                }

                trans.Commit();
                LoadOpts loadOptions = new LoadOpts();
                family = fdoc.LoadFamily(doc, loadOptions);
                #endregion

                #region 材质

                IList<Element> mtset = new FilteredElementCollector(doc)
                    .WherePasses(new ElementClassFilter(typeof(Material))).ToElements();
                transaction.Start("Create Material");
                foreach (string Type in typesList)
                {
                    if (mtset.Select(x => x.Name).ToList().Contains(Type))
                        continue;
                    else
                    {
                        Material material = CreateMaterial(doc, Type, false);
                        Random randomNumFirst = new Random((int)DateTime.Now.Ticks);
                        System.Threading.Thread.Sleep(randomNumFirst.Next(50));
                        Random randomNumSencond = new Random((int)DateTime.Now.Ticks);
                        int intRed = randomNumFirst.Next(256);
                        int intGreen = randomNumSencond.Next(256);
                        int intBlue = intRed + intGreen > 400 ? 0 : 400 - intRed - intGreen;
                        intBlue = intBlue > 255 ? 255 : intBlue;
                        material.Color = new Color((byte)intRed, (byte)intGreen, (byte)intBlue);
                        material.MaterialClass = "地质材质";
                        mtset.Add(material);
                    }
                }

                transaction.Commit();

                #endregion

                int count = 0;
                boreholeList.ForEach(x => count += x.ValueList.Count);

                #region 生成族实例
                using (FilterProgressForm prf1 = new FilterProgressForm("生成", "{0} of " + count.ToString(), count))
                {
                    transaction.Start("Create FamilyInstance");
                    foreach (Borehole borehole in boreholeList)
                    {
                        for (int i = 1; i < borehole.ValueList.Count; i++)
                        {
                            GeologyLayer geologyLayer = borehole.ValueList[i];
                            FamilySymbol familySymbol = new FilteredElementCollector(doc)
                                .OfCategory(BuiltInCategory.OST_GenericModel).OfClass(typeof(FamilySymbol))
                                .First(x => x.Name == geologyLayer.Type) as FamilySymbol;
                            if (!familySymbol.IsActive)
                            {
                                familySymbol.Activate();
                            }

                            FamilyInstance familyInstance = doc.Create.NewFamilyInstance(geologyLayer.Point, familySymbol,
                                StructuralType.NonStructural);

                            familyInstance.LookupParameter("深度")
                                .Set(borehole.ValueList[i - 1].Point.Z - geologyLayer.Point.Z);
                            familyInstance.LookupParameter("材质")
                                .Set(mtset.First(x => x.Name == familyInstance.Name).Id);
                            familyInstance.LookupParameter("孔号").Set(borehole.Name);


                            if (prf1.progressBar1.Tag.ToString() == "Cancel")
                                break;
                            prf1.Increment();
                            Application.DoEvents();
                        }
                    }
                }

                transaction.Commit();

                #endregion
            }
            status = transGroup.Assimilate();
            return Result.Succeeded;

        }
        public Material CreateMaterial(Document doc, string name, bool stru)
        {
            Material material = null;
            try
            {
                ElementId materialId = Material.Create(doc, name);
                material = doc.GetElement(materialId) as Material;
                StructuralAsset strucAsset = new StructuralAsset("uBIM", StructuralAssetClass.Undefined);
                strucAsset.Behavior = StructuralBehavior.Isotropic;
                PropertySetElement propertySet = PropertySetElement.Create(doc, strucAsset);
                propertySet.get_Parameter(BuiltInParameter.PROPERTY_SET_NAME).Set(name);
                propertySet.get_Parameter(BuiltInParameter.PHY_MATERIAL_PARAM_CLASS).Set((int)StructuralMaterialType.Undefined);
                propertySet.get_Parameter(BuiltInParameter.PHY_MATERIAL_PARAM_UNIT_WEIGHT).Set(232);
                material.SetMaterialAspectByPropertySet(MaterialAspect.Structural, propertySet.Id);
            }
            catch
            { }
            return material;
        }
    }
}
