using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Windows;
using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using OfficeOpenXml;

namespace uBIMEarthTools.Commands.DesignDataEntry
{
    /// <summary>
    /// 桩长校核
    /// </summary>
    [Transaction(TransactionMode.Manual)]
    public class DesignDataEntryCommand : IExternalCommand
    {
        public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
        {
            UIDocument uidoc = commandData.Application.ActiveUIDocument;
            Document doc = uidoc.Document;

            var familyNames = new FilteredElementCollector(doc).OfClass(typeof(Family))
                .Where(x => x.Name.Contains("桩")).Select(x => x.Name);
            if (!familyNames.Any())
            {
                MessageBox.Show("文档中不包含桩族");
                return Result.Cancelled;
            }

            if (!(doc.ActiveView is View3D))
            {
                System.Windows.Forms.MessageBox.Show($"请在三维视图下操作");
                return Result.Failed;
            }

            var linkDocuments = new FilteredElementCollector(doc, doc.ActiveView.Id).OfClass(typeof(RevitLinkInstance)).Cast<RevitLinkInstance>();
            Dictionary<string, ObservableCollection<string>> dic =
                new Dictionary<string, ObservableCollection<string>>();
            foreach (var revitLinkInstance in linkDocuments)
            {
                var linkDoc = revitLinkInstance.GetLinkDocument();
                List<string> bearingStratum = new FilteredElementCollector(linkDoc).OfClass(typeof(FamilySymbol)).Where(x => x.Name.Contains("地质")).Select(x => x.Name).Distinct().ToList();
                if (bearingStratum.Any())
                {
                    dic.Add(revitLinkInstance.Name, new ObservableCollection<string>(bearingStratum));
                }
            }

            if (!dic.Any())
            {
                MessageBox.Show("文档中不包含地质链接");
                return Result.Cancelled;
            }

            DesignDataEntry data = new DesignDataEntry()
            {
                FamilyNames = new ObservableCollection<string>(familyNames),
                LinkFiles = new ObservableCollection<string>(linkDocuments.Select(x => x.Name)),
                LinkDictionary = dic
            };
            DesignDataEntryWindow dataEntryWindow = new DesignDataEntryWindow { DataContext = data };
            dataEntryWindow.ShowDialog();

            if (dataEntryWindow.DialogResult == true)
            {
                var instances = new FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_StructuralFoundation).OfClass(typeof(FamilyInstance)).ToElements().Cast<FamilyInstance>().Where(x => x.Symbol.FamilyName == data.SelectedFamily);

                ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
                using (Transaction transaction = new Transaction(doc, "Find Number"))
                {
                    transaction.Start();
                    var linkDocument = linkDocuments.FirstOrDefault(x => x.Name == data.SelectedLink).GetLinkDocument();
                    BoundingBoxXYZ boundingBox = (doc.ActiveView as View3D).GetSectionBox();
                    double maxZ = boundingBox.Min.Z > boundingBox.Max.Z ? boundingBox.Min.Z : boundingBox.Max.Z;
                    double minZ = boundingBox.Min.Z < boundingBox.Max.Z ? boundingBox.Min.Z : boundingBox.Max.Z;
                    ReferenceIntersector referenceIntersector = new ReferenceIntersector(doc.ActiveView as View3D);
                    referenceIntersector.FindReferencesInRevitLinks = true;

                    using (var package = new ExcelPackage(new FileInfo(data.FilePath)))
                    {
                        var worksheet = package.Workbook.Worksheets[0];
                        int endRowNumber = worksheet.Dimension.End.Row;
                        for (int i = 2; i <= endRowNumber; i++)
                        {
                            var name = worksheet.Cells[i, 1].Text;
                            var length = double.Parse(worksheet.Cells[i, 2].Text);

                            foreach (var instance in instances)
                            {
                                if (instance.LookupParameter("桩编号").AsString() == name)
                                {

                                    XYZ xyz = new XYZ((instance.Location as LocationPoint).Point.X, (instance.Location as LocationPoint).Point.Y, maxZ + 10);
                                    List<ReferenceWithContext> referenceWithContexts = referenceIntersector.Find(xyz, -XYZ.BasisZ).Where(x => x.GetReference().ElementReferenceType != ElementReferenceType.REFERENCE_TYPE_NONE).Where(x =>
                                        (linkDocument.GetElement(x.GetReference().LinkedElementId)?.Name.Contains("地质")).HasValue).ToList();

                                    if (referenceWithContexts.Any())
                                    {
                                        double height = referenceWithContexts.OrderBy(x => x.Proximity).First().Proximity;

                                        if (data.Surface)
                                        {
                                            ElementTransformUtils.MoveElement(doc, instance.Id, new XYZ(0, 0, xyz.Z - height - (instance.Location as LocationPoint).Point.Z));
                                        }
                                        else
                                        {
                                            height = xyz.Z - (instance.Location as LocationPoint).Point.Z;
                                        }


                                        foreach (var referenceWithContext in referenceWithContexts)
                                        {
                                            if (linkDocument.GetElement(referenceWithContext.GetReference().LinkedElementId)?.Name == data.SelectedType)
                                            {
                                                var depth = referenceWithContext.Proximity;

                                                var dim = instance.LookupParameter("直径").AsDouble();

                                                depth = depth - height + data.Depth * dim;

                                                instance.LookupParameter("设计桩长").Set(depth);

                                                worksheet.Cells[i, 3].Value = depth * 304.8 / 1000;

                                                break;
                                            }
                                        }

                                        //if (referenceWithContexts.Any(x => linkDocument.GetElement(x.GetReference().LinkedElementId)?.Name == data.SelectedType))
                                        //{
                                        //    var depth = referenceWithContexts.FirstOrDefault(x => linkDocument.GetElement(x.GetReference().LinkedElementId).Name == data.SelectedType).Proximity;

                                        //    var dim = instance.LookupParameter("直径").AsDouble();

                                        //    depth = depth - height + data.Depth * dim;

                                        //    instance.LookupParameter("设计桩长").Set(depth);

                                        //    worksheet.Cells[i, 3].Value = depth * 304.8 / 1000;

                                        //}

                                    }
                                    instance.LookupParameter("实际桩长").Set(length * 1000 / 304.8);
                                    instance.LookupParameter("深度").Set(length * 1000 / 304.8);

                                    //worksheet.Cells[i, 4].Value = (instance.Location as LocationPoint).Point.X;
                                    //worksheet.Cells[i, 5].Value = (instance.Location as LocationPoint).Point.Y;
                                    //worksheet.Cells[i, 6].Value = (instance.Location as LocationPoint).Point.Z;

                                    //if (!string.IsNullOrEmpty(worksheet.Cells[i, 7].Text))
                                    //{
                                    //    var ray = ((double)worksheet.Cells[i, 7].Value) * 304.8;
                                    //    var dim = instance.LookupParameter("直径").AsDouble() * 304.8;
                                    //    ray += (1.5 * dim);

                                    //    instance.LookupParameter("设计桩长").Set(ray / 304.8);
                                    //    worksheet.Cells[i, 3].Value = ray / 1000;
                                    //}
                                }
                            }
                        }
                        package.Save();
                    }

                    transaction.Commit();
                }

            }

            return Result.Succeeded;
        }
    }
}
