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

            // 選択フィルターを設定
            WallSelectionFilter filter = new WallSelectionFilter(doc);

            try
            {
                // フィルター付きでユーザーに壁インスタンスを選択してもらう
                Reference myRef = uidoc.Selection.PickObject(ObjectType.Element, filter, "壁を選択してください。キャンセルするにはESCを押します");

                // 選択された要素を取得
                Element selectElement = doc.GetElement(myRef);
                // ファミリ名、タイプ名、カテゴリを取得
                Wall wall = selectElement as Wall;

                // 移動したい方向と距離。X方向に6400mm移動
                XYZ moveDistance = new XYZ(6400, 0, 0);
                double x = UnitUtils.ConvertToInternalUnits(moveDistance.X, UnitTypeId.Millimeters);
                double y = UnitUtils.ConvertToInternalUnits(moveDistance.Y, UnitTypeId.Millimeters);
                double z = UnitUtils.ConvertToInternalUnits(moveDistance.Z, UnitTypeId.Millimeters);
                XYZ translation = new XYZ(x, y, z);

                using (Transaction tx = new Transaction(doc, "Disallow Wall Joins"))
                {
                    tx.Start();
                    // 壁の両端の連結を解除
                    WallUtils.DisallowWallJoinAtEnd(wall, 0);
                    WallUtils.DisallowWallJoinAtEnd(wall, 1);
                    tx.Commit();
                }

                using (Transaction tx = new Transaction(doc, "Move Wall"))
                {
                    tx.Start();
                    // 壁を移動する
                    ElementTransformUtils.MoveElement(doc, wall.Id, translation);
                    tx.Commit();
                }
                //再度壁の連結を行うには以下を移動後にトランザクションで実行
                //WallUtils.AllowWallJoinAtEnd(wall, 0);
                //WallUtils.AllowWallJoinAtEnd(wall, 1);
            }
            catch (Autodesk.Revit.Exceptions.OperationCanceledException)
            {
                // ユーザーがキャンセルした場合
                return Result.Cancelled;
            }
            catch (Exception ex)
            {
                // その他のエラーが発生した場合
                message = $"エラーが発生しました: {ex.Message}";
                return Result.Failed;
            }
            return Result.Succeeded;
        }
    }
    public class WallSelectionFilter : ISelectionFilter
    {
        private readonly Document doc;
        //コンストラクタ
        public WallSelectionFilter(Document doc)
        {
            this.doc = doc;
        }
        //要素の選択を許可するかどうかのメソッド
        public bool AllowElement(Element elem)
        {
            if (elem is Autodesk.Revit.DB.Wall)
            {
                return true;
            }
            return false;
        }
        //要素の面やエッジなどジオメトリへの参照を選択できるかどうかのメソッド
        public bool AllowReference(Reference reference, XYZ position)
        {
            return false;
        }
    }
}
