#region Namespaces
using System;
using System.Collections.Generic;
using System.Diagnostics;
using Autodesk.Revit.ApplicationServices;
using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using Autodesk.Revit.UI.Selection;

#endregion

namespace RevitAddinCreateFloor
{
    [Transaction(TransactionMode.Manual)]
    public class Command : IExternalCommand
    {
        public Result Execute(
          ExternalCommandData commandData,
          ref string message,
          ElementSet elements)
        {
            UIApplication uiapp = commandData.Application;
            UIDocument uidoc = uiapp.ActiveUIDocument;
            Application app = uiapp.Application;
            Document doc = uidoc.Document;

            //*******条件**********
            //床タイプ
            string floorTypeName = "一般 150 mm";
            //床の位置、外形（CurveLoop）
            //4点を設定する
            XYZ p1 = new XYZ(0, 0, 0);
            XYZ p2 = new XYZ(Uni(14400), 0, 0);
            XYZ p3 = new XYZ(Uni(14400), Uni(7200), 0);
            XYZ p4 = new XYZ(0, Uni(7200), 0);
            //4点を結ぶ線を作成する
            CurveLoop profile = new CurveLoop();
            profile.Append(Line.CreateBound(p1, p2));
            profile.Append(Line.CreateBound(p2, p3));
            profile.Append(Line.CreateBound(p3, p4));
            profile.Append(Line.CreateBound(p4, p1));
            //開口部1の設定
            //4点を設定する
            XYZ p5 = new XYZ(Uni(1800), Uni(1800), 0);
            XYZ p6 = new XYZ(Uni(3600), Uni(1800), 0);
            XYZ p7 = new XYZ(Uni(3600), Uni(5400), 0);
            XYZ p8 = new XYZ(Uni(1800), Uni(5400), 0);
            //4点を結ぶ線を作成する
            CurveLoop opening1 = new CurveLoop();
            opening1.Append(Line.CreateBound(p5, p6));
            opening1.Append(Line.CreateBound(p6, p7));
            opening1.Append(Line.CreateBound(p7, p8));
            opening1.Append(Line.CreateBound(p8, p5));
            //開口部2の設定
            //4点を設定する
            XYZ p9 = new XYZ(Uni(10800), Uni(1800), 0);
            XYZ p10 = new XYZ(Uni(12600), Uni(1800), 0);
            XYZ p11 = new XYZ(Uni(12600), Uni(5400), 0);
            XYZ p12 = new XYZ(Uni(10800), Uni(5400), 0);
            //4点を結ぶ線を作成する
            CurveLoop opening2 = new CurveLoop();
            opening2.Append(Line.CreateBound(p9, p10));
            opening2.Append(Line.CreateBound(p10, p11));
            opening2.Append(Line.CreateBound(p11, p12));
            opening2.Append(Line.CreateBound(p12, p9));


            //現在開いている平面ビューのレベルを取得する
            Level level = null;
            View activeView = uidoc.ActiveView;
            //平面ビューか？
            if (activeView is ViewPlan viewPlan)
            {
                // 平面ビューのレベルを取得
                level = doc.GetElement(viewPlan.GenLevel.Id) as Level;
            }
            else
            {
                TaskDialog.Show("エラー", "現在のビューは平面ビューではありません。");
                return Result.Failed;
            }

            //床タイプを検索する
            FloorType floorType = null;
            try
            {
                floorType = new FilteredElementCollector(doc).OfClass(typeof(FloorType)).Where(typ => typ.Name == floorTypeName).First() as FloorType;
                //床を作成する
                if (floorType != null && level != null)
                {
                    using (Transaction tx = new Transaction(doc))
                    {
                        tx.Start("Create Floor");
                        //床作成
                        //Line slopeArrow = Line.CreateBound(new XYZ(10, 10, 0), new XYZ(11, 10, 0));
                        Floor floor = Floor.Create(doc, new List<CurveLoop> { profile , opening1 , opening2 }, floorType.Id, level.Id, true, null,0);
                        tx.Commit();
                    }
                }
            }
            catch (Exception ex)
            {
                // 例外が発生した場合のエラーメッセージ
                TaskDialog.Show("エラー", $"指定された床タイプ '{floorTypeName}' が見つかりません。エラーメッセージ：{ex.Message}");
                return Result.Failed;
            }
            return Result.Succeeded;
        }
        //ミリメートル単位を内部長さ単位に変換
        private double Uni(double x)
        {
            return  UnitUtils.ConvertToInternalUnits(x, UnitTypeId.Millimeters);
        }
    }
}
