#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 RevitAddinCreateWall
{
    [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;

            /*
            //複数の壁を作りたい場合には次のデータを用意します。
            //4点を設定する
            XYZ p1 = new XYZ(Uni(20000), Uni(800), 0);
            XYZ p2 = new XYZ(Uni(25000), Uni(800), 0);
            XYZ p3 = new XYZ(Uni(25000), Uni(5800), 0);
            XYZ p4 = new XYZ(Uni(20000), Uni(5800), 0);
            //各点を結ぶ線を作りリストに格納する
            List<Curve> wallLines = new List<Curve>();
            wallLines.Add(Line.CreateBound(p1, p2));
            wallLines.Add(Line.CreateBound(p2, p3));
            wallLines.Add(Line.CreateBound(p3, p4));
            wallLines.Add(Line.CreateBound(p4, p1));
            */

            //*******条件**********
            //壁タイプ
            string newWallTypeName = "(L#)EB1/EB1";
            // 壁の位置（直線Line）
            double startX = 19200; startX= UnitUtils.ConvertToInternalUnits(startX, UnitTypeId.Millimeters);
            double startY = 400; startY = UnitUtils.ConvertToInternalUnits(startY, UnitTypeId.Millimeters);
            double startZ = 0; startZ = UnitUtils.ConvertToInternalUnits(startZ, UnitTypeId.Millimeters);
            XYZ start = new XYZ(startX, startY, startZ);
            double endX = 19200; endX = UnitUtils.ConvertToInternalUnits(endX, UnitTypeId.Millimeters);
            double endY = 13200- 400; endY = UnitUtils.ConvertToInternalUnits(endY, UnitTypeId.Millimeters);
            double endZ = 0; endZ = UnitUtils.ConvertToInternalUnits(endZ, UnitTypeId.Millimeters);
            XYZ end = new XYZ(endX, endY, endZ);
            //壁の直線Lineを作る
            Line line = Line.CreateBound(start, end);

            //壁の高さ
            double height = 2858;
            height = UnitUtils.ConvertToInternalUnits(height, UnitTypeId.Millimeters);

            //基準高さからのオフセット
            double offset = 0;

            //現在開いている平面ビューのレベルを取得する
            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;
            }

            //壁タイプを検索する
            WallType wallType = null;
            try
            {
                wallType = new FilteredElementCollector(doc).OfClass(typeof(WallType)).Where(typ => typ.Name == newWallTypeName).First() as WallType;
                //壁を作成する
                if (wallType != null)
                {
                    using (Transaction tx = new Transaction(doc))
                    {
                        tx.Start("Create Wall");
                        // １つの壁作成
                        Wall wall = Wall.Create(doc, line, wallType.Id, level.Id, height, offset, false, false);
                        // 壁の結合を許可する
                        WallUtils.AllowWallJoinAtEnd(wall, 0);
                        WallUtils.AllowWallJoinAtEnd(wall, 1);

                        /*
                        //複数の壁を一気に作るには以下を使う
                        foreach (var wallLine in wallLines)
                        {
                            Wall wall = Wall.Create(doc, wallLine, wallType.Id, level.Id, height, offset, false, false);
                            // 壁の結合を許可する
                            WallUtils.AllowWallJoinAtEnd(wall, 0);
                            WallUtils.AllowWallJoinAtEnd(wall, 1);
                        }
                        */
                        tx.Commit();
                    }
                }
            }
            catch (Exception ex)
            {
                // 例外が発生した場合のエラーメッセージ
                TaskDialog.Show("エラー", $"指定された壁タイプ '{newWallTypeName}' が見つかりません。エラーメッセージ：{ex.Message}");
                return Result.Failed;
            }
            
            return Result.Succeeded;
        }
        //ミリメートル単位を内部長さ単位に変換
        private double Uni(double x)
        {
            return UnitUtils.ConvertToInternalUnits(x, UnitTypeId.Millimeters);
        }
    }
}
