--
-- ルカV4xE.V.E.C.エディター

--
-- プラグインマニフェスト関数.
--
function manifest()
    myManifest = {
        name          = "ルカV4XE.V.E.C.エディター",
        comment       = "VOCALOIDEditorでE.V.E.C.を操作します",
        author        = "きょん☆さん",
        pluginID      = "{2db83a7b-e261-4182-a39b-63510f23684b}",
        pluginVersion = "1.0.0.4",
        apiVersion    = "3.0.0.1"
    }
    
    return myManifest
end

-- ノートイベント配列.
noteListEX = {}
phtbl = {"a", "i", "M", "e", "o", "N\\", "N", "J", "m'", "n", "m", "N"}

--- split関数
function split(str, del)
  p, nrep = str:gsub("%s*"..del.."%s*", "")
  return { str:match((("%s*(.-)%s*"..del.."%s*"):rep(nrep).."(.*)")) }
end

--
-- スクリプトのエントリポイント関数.
--
function main(processParam, envParam)
	-- 実行時に渡されたパラメータを取得する.
	local beginPosTick = processParam.beginPosTick	-- 選択範囲の始点時刻（ローカルTick）.
	local endPosTick   = processParam.endPosTick	-- 選択範囲の終点時刻（ローカルTick）.
	local songPosTick  = processParam.songPosTick	-- カレントソングポジション時刻（ローカルTick）.

	-- 実行時に渡された実行環境パラメータを取得する.
	local scriptDir  = envParam.scriptDir	-- Luaスクリプトが配置されているディレクトリパス（末尾にデリミタ "\" を含む）.
	local scriptName = envParam.scriptName	-- Luaスクリプトのファイル名.
	local tempDir    = envParam.tempDir		-- Luaプラグインが利用可能なテンポラリディレクトリパス（末尾にデリミタ "\" を含む）.
	local preset = {}
	--設定ファイルの読み込み
	df = 1
	file = io.open("luka_EVEC.dat", "r")
	if file then
		for idz = 0, 7 do
			preset[idz] = file:read()
			if preset[idz] == nil then
				df = 0
			end
     	end
     end
	if(file == nil) then
		df = 0
	end
	--設定ファイルがない場合のデフォルト値
	if df == 0 then
		preset[0] = "なし,Whisper,Soft,Husky,Native,Power1,Power2,Cute,Dark,Falsetto"
		preset[1] = "なし,Breath-Short,Breath-Long"
		preset[2] = "なし,×２,×３,×４"
		preset[3] = "－"
		preset[4] = 45
		preset[5] = 60
		preset[6] = 1
		preset[7] = 1
	end

	-- パラメータ入力ダイアログのウィンドウタイトルを設定する.
	VSDlgSetDialogTitle("ルカV4xE.V.E.C.エディター")

	-- ダイアログにフィールドを追加する.
	local field = {}
	field.name       = "ColorType"
	field.caption    = "Voice Color"
	field.initialVal = preset[0]
	field.type = 4
	dlgStatus  = VSDlgAddField(field)

	field.name       = "ReleaseType"
	field.caption    = "Voice Release"
	field.initialVal = preset[1]
	field.type = 4
	dlgStatus  = VSDlgAddField(field)
	
	field.name       = "phetbl"
	field.caption    = "子音拡張"
	field.initialVal = preset[2]
	field.type = 4
	dlgStatus  = VSDlgAddField(field)

	field.name       = "Cly"
	field.caption    = "Color・Release部分lyric"
	field.initialVal = preset[3]
	field.type       = 3
	dlgStatus = VSDlgAddField(field)

	field.name       = "Vlen"
	field.caption    = "先頭ノート長さ（45）通常はこのまま"
	field.initialVal = preset[4]
	field.type       = 0
	dlgStatus = VSDlgAddField(field)

	field.name       = "Rlen"
	field.caption    = "Release長さ（60）通常はこのまま"
	field.initialVal = preset[5]
	field.type       = 0
	dlgStatus = VSDlgAddField(field)

	field.name       = "PHPro"
	field.caption    = "Color・Releaseの発音記号をプロテクト"
	field.initialVal = preset[6]
	field.type       = 1
	dlgStatus = VSDlgAddField(field)

	field.name       = "prsn"
	field.caption    = "この設定値をデフォルトにする"
	field.initialVal = preset[7]
	field.type       = 1
	dlgStatus = VSDlgAddField(field)

	-- ダイアログから入力値を取得する.
	dlgStatus = VSDlgDoModal()
	if  (dlgStatus ~= 1) then
		return 0
	end

	-- ダイアログから入力値を取得する.
	dlgStatus, ColorType = VSDlgGetStringValue("ColorType")
	dlgStatus, ReleaseType = VSDlgGetStringValue("ReleaseType")
	dlgStatus, phetbl = VSDlgGetStringValue("phetbl")
	dlgStatus, Cly = VSDlgGetStringValue("Cly")
	dlgStatus, Vlen = VSDlgGetIntValue("Vlen")
	dlgStatus, Rlen = VSDlgGetIntValue("Rlen")
	dlgStatus, PHPro = VSDlgGetBoolValue("PHPro")
	dlgStatus, prsn = VSDlgGetBoolValue("prsn")

	if ColorType == "なし" then
		preset[0] = "なし,Whisper,Soft,Husky,Native,Power1,Power2,Cute,Dark,Falsetto"
		colorex = ""
	end

	if ColorType == "Whisper" then
		preset[0] = "Whisper,なし,Soft,Husky,Native,Power1,Power2,Cute,Dark,Falsetto"
		colorex = "#1"
	end

	if ColorType == "Soft" then
		preset[0] = "Soft,なし,Whisper,Husky,Native,Power1,Power2,Cute,Dark,Falsetto"
		colorex = "#2"
	end

	if ColorType == "Husky" then
		preset[0] = "Husky,なし,Whisper,Soft,Native,Power1,Power2,Cute,Dark,Falsetto"
		colorex = "#3"
	end

	if ColorType == "Native" then
		preset[0] = "Native,なし,Whisper,Soft,Husky,Power1,Power2,Cute,Dark,Falsetto"
		colorex = "#4"
	end

	if ColorType == "Power1" then
		preset[0] = "Power1,なし,Whisper,Soft,Husky,Native,Power2,Cute,Dark,Falsetto"
		colorex = "#5"
	end

	if ColorType == "Power2" then
		preset[0] = "Power2,なし,Whisper,Soft,Husky,Native,Power1,Cute,Dark,Falsetto"
		colorex = "#6"
	end

	if ColorType == "Cute" then
		preset[0] = "Cute,なし,Whisper,Soft,Husky,Native,Power1,Power2,Dark,Falsetto"
		colorex = "#+"
	end

	if ColorType == "Dark" then
		preset[0] = "Dark,なし,Whisper,Soft,Husky,Native,Power1,Power2,Cute,Falsetto"
		colorex = "#-"
	end

	if ColorType == "Falsetto" then
		preset[0] = ",Falsetto,なし,Whisper,Soft,Husky,Native,Power1,Power2,Cute,Dark"
		colorex = "#F"
	end

	if ReleaseType == "なし" then
		preset[1] = "なし,Breath-Short,Breath-Long"
		Relex = ""
	end

	if ReleaseType == "Breath-Short" then
		preset[1] = "Breath-Short,Breath-Long,なし"
		rtype = "BS"
		Relex = "*#1"
	end

	if ReleaseType == "Breath-Long" then
		preset[1] = "Breath-Long,なし,Breath-Short"
		rtype = "BL"
		Relex = "*#2"
	end

	if phetbl == "なし" then
		preset[2] = "なし,×２,×３,×４"
		phex = 1
	end

	if phetbl == "×２" then
		preset[2] = "×２,なし,×３,×４"
		phex = 2
	end

	if phetbl == "×３" then
		preset[2] = "×３,なし,×２,×４"
		phex = 3
	end

	if phetbl == "×４" then
		preset[2] = "×４,なし,×２,×３"
		phex = 4
	end

	if (colorex == "") and (Relex == "") and (phex == 1) then
		VSMessageBox("Voice colore・Voice Release・子音拡張のいずれかをを指定してください。", 0)
		return 0
	end

	preset[3] =	Cly
	preset[4] = Vlen
	preset[5] = Rlen
	preset[6] = PHPro
	preset[7] = prsn

	-- 終了コード.
	local endStatus = 0

	-- 変数・定数の定義
	local noteListEX = {}
	local note     = {}
	local noteCount
	local retCode
	local idx

	-- ノートを取得してノートイベント配列へ格納します.
	VSSeekToBeginNote()
	idx = 1
	retCode, note = VSGetNextNoteEx()
	while (retCode == 1) do
		-- 取得したノートを配列へ格納する.
		noteListEX[idx] = note
		retCode, note = VSGetNextNoteEx()
		idx = idx + 1
	end

	-- 読み込んだノートの総数.
	noteCount = table.getn(noteListEX)
	if (noteCount == 0) then
		VSMessageBox("読み込んだノートがありません。", 0)
		return 0
	end

	-- 選択音符を判定
	local startNote = noteCount + 1	-- 最初の選択音符
	local endNote = 0		-- 最後の選択音符
	local noteStartPos		-- 音符の開始時刻
	local noteEndPos		-- 音符の終了時刻

	for idx = 1, noteCount do
		noteStartPos = noteListEX[idx].posTick
		noteEndPos   = noteListEX[idx].posTick + noteListEX[idx].durTick
		-- 音符が選択範囲内に入っていた場合
		if ( (beginPosTick <= noteStartPos) and (noteEndPos <= endPosTick) ) then
			if (idx < startNote ) then
				startNote = idx
			end
			if (idx > endNote) then
				endNote = idx
			end
		end
	end

	-- ノートが選択されていない場合
	if (endNote == 0) then
		VSMessageBox("ノートが選択されていません。", 0)
		return 0
	end

	--複数ノート選択に制限をかける（暫定）
	if endNote - startNote > 0 then
		local BoxStatus
		BoxStatus = VSMessageBox("複数のノートが選択されています。\nよろしいですか？",4)
		if( BoxStatus == 7 ) then
			return 0
		end
	end

	-- 処理ループ.
	for idx =  startNote, endNote do
		local updNote = {}
		updNote = noteListEX[idx]
		erf = 0
		durTickm = updNote.durTick
		posTickm = updNote.posTick
		vibratoTypem = updNote.vibratoType
		lenmax = 90
		if (colorex == "") and (Relex ~= "") then
			lenmax = 120
		end
		if (colorex ~= "") and (Relex ~= "") then
			lenmax = 150
		end
		if (colorex == "") and (Relex == "") then
			lenmax = 0
		end
		if durTickm < lenmax then
			erf = 1
		end
		local phfl = 0
		phoneV = ""
		for i = 1, 12 do
			if phtbl[i] == updNote.phonemes then
				phoneC = updNote.phonemes
				phfl = 1
			end
		end
		if phfl == 0 then
			phoneCV = split(updNote.phonemes, " ")
			phoneC = phoneCV[1]
			phoneV = phoneCV[2]
			if (phoneV == nil) then
				phoneV = ""
			end
			if (phoneC.." "..phoneV) ~= updNote.phonemes then
				erf = 1
			end
		end

		for i = 1, 5 do
			if phtbl[i] == phoneV then
			phfl = 2
			end
		end

		if phfl == 0 then
			erf = 1
		end

		if phfl == 1 then
			phoneV = phoneC
		end

		--ノートの処理
		if (erf == 0) or ((colorex == "") and (Relex ~= "")) then
			if colorex ~= "" then
				updNote.durTick = Vlen
				updNote.vibratoType = 0
			end
			if (colorex == "") and (Relex ~= "") then
				updNote.durTick = updNote.durTick - Rlen
			end
			if (phex > 1) and (phfl ~= 1) then
				updNote.phonemes = phoneC
				for i = 2,phex do
					updNote.phonemes = updNote.phonemes.." "..phoneC
				end
				updNote.phonemes = updNote.phonemes.." "..phoneV
			end
			retCode = VSUpdateNoteEx(updNote);
			if (retCode ~= 1) then
				VSMessageBox("更新エラー", 0)
				return 0
			end
			--ノートColorの処理
			if (colorex ~= "") then
				local newNoteA = {}
				newNoteA = noteListEX[idx]
				newNoteA.durTick = durTickm - Vlen
				if  Relex ~= "" then
					newNoteA.durTick = newNoteA.durTick - Rlen
				end
				newNoteA.phLock = 0
				if PHPro == 1 then
					newNoteA.phLock = 1
				end
				newNoteA.posTick = newNoteA.posTick + Vlen
				newNoteA.lyric = Cly
				if Cly == "" then
					newNoteA.lyric = ColorType
				end
				newNoteA.phonemes = phoneV..colorex
				newNoteA.vibratoType = vibratoTypem
				retCode = VSInsertNoteEx(newNoteA)
				if(retCode ~= 1) then
					VSMessageBox("更新エラー", 0)
					return 0
				end
			end
			--ノートReleaseの処理
			if Relex ~= "" then
				local newNoteB = {}
				newNoteB = noteListEX[idx]
				newNoteB.phLock = 0
				if PHPro == 1 then
					newNoteB.phLock = 1
				end
				newNoteB.vibratoType = 0
				newNoteB.durTick = Rlen
				newNoteB.posTick = posTickm + durTickm - Rlen
				newNoteB.lyric = Cly
				if Cly == "" then
					newNoteB.lyric = rtype
				end
				newNoteB.phonemes = Relex
				retCode = VSInsertNoteEx(newNoteB)
				if(retCode ~= 1) then
					VSMessageBox("更新エラー", 0)
					return 0
				end
			end
		end
	-- 設定ファイル保存
	if (prsn == 1) then
		f = io.open("luka_EVEC.dat", "w")
		for idz = 0, 7 do
			if f ~=  nil then
				f:write(preset[idz] .. "\n")
			end
		end
		if f == nil then
				VSMessageBox("設定ファイルを保存できませんでした。", 0)
		end
		f:close()
	end
end
	return 0
end
