/**
 * HTML整形スクリプト。開いているファイル全体が対象です。
 * とてつもなく遅いです。 1000行で1分くらいかかるので注意してください。
 *
 * [注意事項]
 * 途中で止めてしまうと以下の設定が変更されたままになります。
 * ・インクリメンタルサーチ  - OFF
 * ・検索の大文字小文字区別  - 区別しない
 */


// インクリメンタルサーチ情報保存
var incSearchFlag = globalSettings.getBoolValue("incSearch");
// インクリメンタルサーチ解除
globalSettings.setBoolValue( "incSearch", 0 );
// 大文字小文字区別サーチ情報保存
var ignorecaseFlag = globalSettings.getBoolValue("ignorecase");
// 大文字小文字区別サーチ解除
globalSettings.setBoolValue( "ignorecase", 1 );

// 1回でUndoできるように
thisView.openUndoBlock();


// とりあえず整形
thisView.viCommand( "\x1b" );
thisView.viCommand( ":%s/</\\n&/g\n" );
thisView.viCommand( ":%s/>/&\\n/g\n" );
thisView.viCommand( ":g/^\s*$/d\n" );
thisView.viCommand( ":g/^\\s*$/d\n" );
thisView.viCommand( ":%s/^\\s*(.*)\\s*$/\\1/\n" );

// 1行目に移動
thisView.setCursorPos( 1,0 );

// インデント調整
var indentLevel = 0; // インデントを行う数
while( thisView.getCursorPos().line != thisView.getLineCount() ){
	var pos = thisView.getCursorPos();
	var line = pos.line;
	var lineStr = thisView.getLineString( line );
	//lineStr = lineStr.substring( pos.offset, lineStr.length() );
	if( lineStr.charAt(0) != "\t" ){
		if( lineStr.charAt(0) == "<" ){
			thisView.viCommand( "mp" ); //	開始位置をpに保存

			lineStr =~ /<\??([^>\s]+)/;
			var tagName      = $1;
			var tagSlash = 1;           // スラッシュ付きなら-1 無しなら 1
			var isFind = 0;         //	見つけたら1に
			var hitCount = 1;   // ヒット数カウント用
			var nestCount = 0;  // ネスト集計用
			var beforePos = pos;

			// 検索文字列設定
			var searchCmd;
			if( tagName.charAt(0) == "/" ){
				tagName = tagName.substring( 1, tagName.length() );
				searchCmd = "?" + "<\\??[\\s\\/]*" + tagName + "[\\s>]\n";
				tagSlash = -1;
			}else{
				searchCmd = "/" + "<\\??[\\s\\/]*" + tagName + "[\\s>]\n";
				tagSlash = 1;
			}

			// 閉じタグを探さないタグ一覧で在れば閉じタグ無しと判断
			var searchFlag = 1;
			var tagNameLower = tagName.toLower();
			var nonSearchTagArray = {"br", "p", "html", "img", "hr", "option", "area" };
			for( var i=0; i<7; i++ ){
				if( tagNameLower == nonSearchTagArray[i] ){
					searchFlag = 0;
				}
			}
			// <!-- だけは完全一致以外もタグ無し扱い
			if( tagNameLower.find( "!--" ) == 0 ){
				searchFlag = 0;
			}

			if( searchFlag ){

				// 一度検索する。開始位置のタグが見つかるはず
				thisView.viCommand( searchCmd );


				while( thisView.isMatched() ) {
					var nowPos  = thisView.getCursorPos();
					var nowLine = thisView.getLineString( nowPos.line );

					// ファイルの先頭/終端を越えたら終了
					if( (nowPos.line - beforePos.line) * tagSlash  < 0 ){
						break;
					}
					nowLine     = nowLine.substring( nowPos.offset, nowLine.length() );

					nowLine = nowLine.replace( /<[\?%]?/, "" );

					if( nowLine.charAt(0) == "/" ) {
						hitCount = hitCount - tagSlash;
					}else{
						hitCount = hitCount + tagSlash;
					}
					if( hitCount > nestCount ) nestCount = hitCount;


					if( hitCount == 0 ) {
						//	見つかった
						isFind = 1;
						break;
					}

					beforePos = nowPos;
					thisView.viCommand( searchCmd );
				}
			}

			if( isFind == 0 ) {
				thisView.viCommand( "`p" ); //	元の位置に戻る
				thisView.insertText( "\t".repeat(indentLevel) );
			}else{
				if(tagSlash == -1){
					indentLevel += tagSlash;
				}
				thisView.insertText( "\t".repeat(indentLevel) );
				thisView.viCommand( "`p" ); //	元の位置に戻る
				thisView.insertText( "\t".repeat(indentLevel) );
				if(tagSlash == 1){
					indentLevel += tagSlash;
				}
			}
		}else{
			thisView.insertText( "\t".repeat(indentLevel) );
		}
	}else{
		indentLevel--;
	}

	// 1行下に下がる
	thisView.setCursorPos( thisView.getCursorPos().line+1, 0 );
}


// インクリメンタルサーチ設定を戻す
globalSettings.setBoolValue( "incSearch", incSearchFlag );
// 大文字小文字区別サーチ設定を戻す
globalSettings.setBoolValue( "ignorecase", ignorecaseFlag );
// マッチ背景を消す
thisView.viCommand( ":cmd 33064\n" );

// 1回でUndoできるように
thisView.closeUndoBlock();