using Autodesk.Revit.ApplicationServices;
using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace RevitAddinApplicatinSample
{
    [Transaction(TransactionMode.Manual)]
    internal class DoorTagExe : 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;
            View activeView = uidoc.ActiveView;

            //使用するドアタグの設定
            string tagFamily = "タグ 建具 ドア";
            string tagType = "STD";

            //使用するドアタグを取得する
            FamilySymbol desiredTag = new FilteredElementCollector(doc)
                    .OfClass(typeof(FamilySymbol))
                    .OfCategory(BuiltInCategory.OST_DoorTags)
                    .Cast<FamilySymbol>()
                    .Where(f => f.Family.Name == tagFamily &&
                    f.Name == tagType)
                    .FirstOrDefault() as FamilySymbol;

            if (desiredTag == null)
            {
                string errorMessage = "以下のファミリがロードされていません。ロードしてからこのアドインを実行してください。";
                errorMessage += $"\nファミリ名={tagFamily}: タイプ名:{tagType}";
                TaskDialog.Show("Error", errorMessage);
                return Result.Failed;
            }

            //activeView のレベルを取得（現在開いているビューのレベル）
            ElementId viewLevelId = activeView.GenLevel != null ? activeView.GenLevel.Id : ElementId.InvalidElementId;

            //現在のビューのレベルにあるドアを取得する
            IList<FamilyInstance> doorsOnLevel = new FilteredElementCollector(doc)
                .OfClass(typeof(FamilyInstance))
                .OfCategory(BuiltInCategory.OST_Doors)
                .Cast<FamilyInstance>()
                .Where(door => door.LevelId == viewLevelId)
                .ToList();

            using (Transaction tx = new Transaction(doc))
            {
                tx.Start("Transaction Add Door Tag");

                //タグモード
                TagMode tagMode = TagMode.TM_ADDBY_CATEGORY;
                //タグの向き
                TagOrientation tagorn = TagOrientation.Horizontal;

                foreach (FamilyInstance door in doorsOnLevel)
                {
                    //doorのReferenceを取得
                    Reference reference = new Reference(door);
                    //doorの位置を取得
                    LocationPoint doorLocation = door.Location as LocationPoint;
                    //タグの位置を決定
                    XYZ tagLocation = new XYZ(doorLocation.Point.X, doorLocation.Point.Y, doorLocation.Point.Z);
                    //タグを作成
                    IndependentTag newTag = IndependentTag.Create(doc, activeView.Id, reference, true, tagMode, tagorn, tagLocation);
                    //ドアタグのタイプを変更する
                    newTag.ChangeTypeId(desiredTag.Id);

                    //引き出し線を表示
                    newTag.get_Parameter(BuiltInParameter.LEADER_LINE).Set(1);
                    //タグの位置を調節する（フィート単位）
                    XYZ headerPnt = tagLocation + new XYZ(4.0, 3.0, 0.0);
                    newTag.TagHeadPosition = headerPnt;
                    //引き出し線のエルボー位置を設定する
                    newTag.LeaderEndCondition = LeaderEndCondition.Attached; //LeaderEndCondition.Free;
                    XYZ elbowPnt = tagLocation + new XYZ(1.0, 3.0, 0.0);
                    newTag.SetLeaderElbow(reference, elbowPnt);
                }
                tx.Commit();
            }
            return Result.Succeeded;
        }
    }
}
