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

#endregion

namespace RevitAddinAddRoomTags
{
    [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;
            View activeView = uidoc.ActiveView;

            //使用する部屋タグの設定
            string tagFamily = "タグ 部屋 一般";
            string tagType = "名前 1.5mm";

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

            if (desiredTag == null)
            {
                string errorMessage = "以下のファミリがロードされていません。ロードしてからこのアドインを実行してください。";
                errorMessage += $"\nファミリ名={tagFamily}: タイプ名:{tagType}";
                TaskDialog.Show("Error", errorMessage);
                return Result.Failed;
            }
            //部屋タグをつける対象の部屋を取得する
            //面積ゼロの部屋は除外するフィルターを用意する
            ParameterValueProvider areaProvider = new ParameterValueProvider(new ElementId(BuiltInParameter.ROOM_AREA));
            ElementParameterFilter areaFilter = new ElementParameterFilter(new FilterDoubleRule(areaProvider, new FilterNumericGreater(), 0, 0.0001));

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

            //現在のビューのレベルにある部屋を取得する。ただし面積ゼロの部屋は除外する
            var roomsOnLevel = new FilteredElementCollector(doc)
                .OfCategory(BuiltInCategory.OST_Rooms)
                .WherePasses(areaFilter)
                .Cast<Room>()
                .Where(room => room.LevelId == viewLevelId)
                .ToList();

            using (Transaction tx = new Transaction(doc))
            {
                tx.Start("Add room tag");
                foreach (Room room in roomsOnLevel)
                {
                    //タグを付ける位置決定のためRoomの位置を取得
                    LocationPoint cen = room.Location as LocationPoint;
                    if (cen != null)
                    {
                        //タグの位置はRoomの中心とする。UV座標系で指定する
                        UV tagLocation = new UV(cen.Point.X, cen.Point.Y);
                        //部屋タグを作成する
                        LinkElementId roomId = new LinkElementId(room.Id);
                        RoomTag roomTag = doc.Create.NewRoomTag(roomId, tagLocation, activeView.Id);
                        //部屋タグのタイプを変更する
                        roomTag.ChangeTypeId(desiredTag.Id);
                    }
                }
                tx.Commit();
            }
            return Result.Succeeded;
        }
    }
}
