-- vim:set ft=lua:
dofile(mg.script_name:gsub('[^\\/]*$','')..'util.lua')

ct={'<?xml version="1.0" encoding="UTF-8" ?><entry>'}

LIBRARY_LIST=GetLibraryPathList()
MEDIA_EXTENSION_LIST={}
for v in edcb.GetPrivateProfile('SET','MEDIA_EXTENSION_LIST','.mp4,.webm',INI):gmatch('[^,]+') do
  MEDIA_EXTENSION_LIST[#MEDIA_EXTENSION_LIST+1]=v
end
HIDE_DIR_LIST={}
for v in edcb.GetPrivateProfile('SET','HIDE_DIR_LIST','chapters',INI):gmatch('[^,]+') do
  HIDE_DIR_LIST[#HIDE_DIR_LIST+1]=v
end


tools=PathAppend(EdcbModulePath(),'Tools')
if WIN32 then
  for s in ('ffmpeg\\ffmpeg.exe|ffmpeg.exe'):gmatch('[^|]+') do
    if EdcbFindFilePlain(PathAppend(tools,s)) then
      ffmpeg='"'..PathAppend(tools,s)..'"'
      break
    end
  end
else
  ffmpeg=FindToolsCommand('ffmpeg')
end
autoMakeThumbs=ffmpeg and {}
thumbsDir=PathAppend(PathAppend(mg.document_root,'video'),'thumbs')
function MakeThumbs(fpath, check)
  local thumbHash=mg.md5(fpath:lower())
  local thumbPath=PathAppend(thumbsDir,thumbHash..'.jpg')
  if not EdcbFindFilePlain(thumbPath) then
    if check then
      if autoMakeThumbs then autoMakeThumbs[#autoMakeThumbs+1]=fpath end
      return
    end
    local cmd=ffmpeg..' -ss 30 -i '..QuoteCommandArgForPath(fpath)..' -vframes 1 -f image2 -s 480x270 '..QuoteCommandArgForPath(thumbPath)
    edcb.os.execute(WIN32 and '"'..cmd..'"' or cmd)
  end
  return thumbHash
end

function GetPgtxt(fpath)
  local f,s,code,cmd
  local ext=fpath:match('%.[0-9A-Za-z]+$') or ''
  local extts=edcb.GetPrivateProfile('SET','TSExt','.ts','EpgTimerSrv.ini')
  if IsEqualPath(ext,extts) then
    -- TSファイルから抽出
    code=500
    local tspgtxt=FindToolsCommand('tspgtxt')
    local cmd=tspgtxt..' -o - '..QuoteCommandArgForPath(fpath)
    f=edcb.io.popen(WIN32 and '"'..cmd..'"' or cmd)
    if f then
      s=f:read('*a') or ''
      if s:find('^\xef\xbb\xbf') then
        code=200
        s=s:sub(4)
      end
      f:close()
    end
  else
    fpath=fpath:gsub('%.[0-9A-Za-z]+$','')
    if EdcbFindFilePlain(fpath..'.psc') then
      -- 書庫から抽出
      code=500
      local dur=nil
      local psisimux=FindToolsCommand('psisimux')
      cmd=psisimux..' -r 0 -p -y .psc -e '..QuoteCommandArgForPath(fpath..'.psc')..' -'
      f=edcb.io.popen(WIN32 and '"'..cmd..'"' or cmd,'r'..POPEN_BINARY)
      if f then
        local buf=f:read(188)
        if buf and #buf==188 then
          dur=GetLeNumber(buf,25,4)
        end
        f:close()
      end
      if dur then
        tspgtxt=FindToolsCommand('tspgtxt')
        cmd=psisimux..' -m '..math.floor(dur/2)..' -y .psc -e '..QuoteCommandArgForPath(fpath..'.psc')..' - | '..tspgtxt..' -o - -'
        f=edcb.io.popen(WIN32 and '"'..cmd..'"' or cmd)
        if f then
          s=f:read('*a') or ''
          if s:find('^\xef\xbb\xbf') then
            code=200
            s=s:sub(4)
          end
          f:close()
        end
      end
    else
      -- 番組情報ファイルを返す
      f=edcb.io.open(fpath..'.program.txt','rb')
      if f then
        s=f:read('*a') or ''
        if s:find('^\xef\xbb\xbf') then
          code=200
          s=s:sub(4)
        elseif s:find('^[^\n]*～') or s:find('^[^\n]*未') then
          -- BOMはないがUTF-8っぽい
          code=200
        elseif s~='' then
          -- Shift_JIS。環境によっては変換できない
          code=500
          s=edcb.Convert('utf-8','cp932',s)
          if s and s~='' then
            code=200
          end
        end
      end
    end
  end
  if code==200 then return s end
end

tsx=edcb.GetPrivateProfile('SET','TSExt','.ts','EpgTimerSrv.ini')
xlist={tsx,table.unpack(MEDIA_EXTENSION_LIST)}

if mg.get_var(mg.request_info.query_string,'thumbs') then
  AssertCsrf(mg.request_info.query_string)

  thumbsUsing={}

  function finddir(path)
    local i=0
    local t=edcb.FindFile(PathAppend(path,'*'),0) or {}
    return function() i=i+1 return t[i] end
  end

  function attrdir(path)
    for v in finddir(path) do
      local fname=v.name
      if fname ~= '.' and fname ~= '..' then
        fpath=PathAppend(path,fname)
        if not v.iserr then
          if v.isdir then
            local hide
            for i,v in ipairs(HIDE_DIR_LIST) do
              if fname == v then hide=true end
            end
            if not hide and not fpath:find(PathAppend('video','thumbs$')) then
              attrdir(fpath)
            end
          else
            for i,ext in ipairs(xlist) do
              if #fname>#ext and IsEqualPath(fname:sub(-#ext),ext) then
                thumbHash=MakeThumbs(fpath)
                thumbsUsing[thumbHash]=true
                break
              end
            end
          end
        end
      end
    end
  end

  if not EdcbFindFilePlain(thumbsDir) then
    edcb.os.execute('mkdir '..QuoteCommandArgForPath(thumbsDir))
  end
  for i,v in ipairs(LIBRARY_LIST) do
    attrdir(v)
  end

  -- 未使用サムネを掃除
  for i,v in ipairs(edcb.FindFile(PathAppend(thumbsDir,'????????????????????????????????.jpg'), 0) or {}) do
    if v.name:match('^%x+%.[Jj][Pp][Gg]$') and not thumbsUsing[v.name:match('^%x+'):lower()] then
      edcb.os.remove(PathAppend(thumbsDir,v.name))
    end
  end

  table.insert(ct, '<info>サムネを作成しました</info></entry>')
else
  dirname=nil
  index=GetVarInt(mg.request_info.query_string,'i',1,#LIBRARY_LIST)
  if index then
    dir=LIBRARY_LIST[index]
    if dir then
      dirhash=mg.get_var(mg.request_info.query_string,'d')
      if dirhash then
        pathname=LIBRARY_LIST[index]
        for j=0,10000 do
          local w=mg.get_var(mg.request_info.query_string, 'p', j)
          if not w then break end
          pathhash=(pathhash and pathhash..',' or '')..w
          for i,v in ipairs(edcb.FindFile(PathAppend(dir,'*'),0) or {}) do
            if v.isdir and not v.name:find('^%.') and mg.md5(v.name)==w then
              dir=PathAppend(dir,v.name)
              pathname=pathname..'/'..v.name
              break
            end
          end
        end
        for i,v in ipairs(edcb.FindFile(PathAppend(dir,'*'),0) or {}) do
          if v.isdir and not v.name:find('^%.') and mg.md5(v.name)==dirhash then
            dir=PathAppend(dir,v.name)
            dirname=v.name
            break
          end
        end
      else
        dirname=LIBRARY_LIST[index]
      end
    end
  end

  if not dirname then
    if dirhash then
      table.insert(ct, '<error>見つかりませんでした</error>')
    else
      table.insert(ct, '<dirname>ホーム</dirname>')

      edcb.htmlEscape=15
      for i,v in ipairs(LIBRARY_LIST) do
        table.insert(ct, '<dir><index>'
          ..i..'</index><name>'
          ..EdcbHtmlEscape(NativeToDocumentPath(v) or v)..'</name></dir>\n'
        )
      end
    end
  else
    hash=mg.get_var(mg.request_info.query_string,'h')
    if not hash then
      ff={}
      for i,v in ipairs(edcb.FindFile(PathAppend(dir,'*'),0) or {}) do
        if not v.isdir then
          for j,ext in ipairs(xlist) do
            if #v.name>#ext and IsEqualPath(v.name:sub(-#ext),ext) then
              ff[#ff+1]=v
              break
            end
          end
        elseif not v.name:find('^%.') then
          local hide
          for j,w in ipairs(HIDE_DIR_LIST) do
            if v.name == w then
              hide=true
              break
            end
          end
          if not hide and not PathAppend(dir,v.name):find(PathAppend('video','thumbs$')) then ff[#ff+1]=v end
        end
      end

      edcb.htmlEscape=15
      table.insert(ct, '<index>'
        ..index..'</index><dirname>'
        ..EdcbHtmlEscape(NativeToDocumentPath(dirname) or dirname)..'</dirname>'
        ..(dirhash and '<dirhash>'..dirhash..'</dirhash>' or '')
        ..(pathname and '<pathname>'..EdcbHtmlEscape(pathname)..'</pathname>' or '')
        ..(pathhash and '<pathhash>'..EdcbHtmlEscape(pathhash)..'</pathhash>' or '')
        ..(NativeToDocumentPath(dir) and '<public>1</public>' or '')
        ..'\n'
      )
      for i,v in ipairs(ff) do
        local thumbHash
        if not v.isdir then
          thumbHash=MakeThumbs(PathAppend(dir,v.name), true)
        end
        table.insert(ct, (v.isdir and '<dir>' or '<file>')..'<name>'
          ..EdcbHtmlEscape(v.name)..'</name><hash>'
          ..mg.md5(v.name)..'</hash><date>'
          ..TimeWithZone(v.mtime, 9*3600)..'</date><size>'
          ..(v.isdir and '' or math.floor(v.size/1048576))..'</size>'
          ..(thumbHash and '<thumb>'..thumbHash..'</thumb>' or '')
          ..(v.isdir and '</dir>' or '</file>')
          ..'\n'
        )
      end
    else
      info=nil
      for i,v in ipairs(xlist) do
        for j,w in ipairs(edcb.FindFile(PathAppend(dir,'*'..v),0) or {}) do
          if not w.isdir and mg.md5(w.name)==hash then
            info=w
            info.ists=v==tsx
            break
          end
        end
        if info then
          break
        end
      end
      if info then
        edcb.htmlEscape=15
        ref=PathAppend(dir,info.name)
        table.insert(ct, '<file><path>'
            ..(NativeToDocumentPath(ref) and EdcbHtmlEscape(NativeToDocumentPath(ref))..'</path><public>1</public>'
                                          or EdcbHtmlEscape(ref)..'</path>\n')..'<name>'
          ..EdcbHtmlEscape(info.name)..'</name><hash>'
          ..mg.md5(info.name)..'</hash><date>'
          ..TimeWithZone(info.mtime, 9*3600)..'</date><size>'
          ..math.floor(info.size/1048576)..'</size>'
        )
        basic=(tonumber(mg.get_var(mg.request_info.query_string,'basic')) or 1)~=0
        if not basic then
          pgtxt=GetPgtxt(ref)
          if pgtxt then table.insert(ct, '<programInfo>'..EdcbHtmlEscape(pgtxt)..'</programInfo>') end
        end

        if info.ists then
          local tsreadex=FindToolsCommand('tsreadex')
          local ffprobe
          if WIN32 then
            for s in ('ffmpeg\\ffprobe.exe|ffprobe.exe'):gmatch('[^|]+') do
              if EdcbFindFilePlain(PathAppend(tools,s)) then
                ffprobe='"'..PathAppend(tools,s)..'"'
                break
              end
            end
          else
            ffprobe=FindToolsCommand('ffprobe')
          end
          f=edcb.io.open(ref, 'rb')
          if f then
            audio=0
            fsec,fsize=GetDurationSec(f)
            f:close()
            if ffprobe then
              offset=math.floor(fsize*10/100/188)*188
              cmd=ffprobe..' -i pipe:0 -hide_banner 2>&1'
              cmd=tsreadex..' -s '..offset..' "'..ref..'" | '..cmd
              local fp=edcb.io.popen(WIN32 and '"'..cmd..'"' or cmd,'r'..POPEN_BINARY)
              if fp then
                for v in fp:read('*a'):gmatch(':%sAudio:%s(.-)\r\n') do
                  audio=audio+1
                end
              end
            end
            table.insert(ct, '<meta>'..(fsec~=0 and '<duration>'..fsec..'</duration>' or '')..'<audio>'..audio..'</audio></meta>')
          end
        end
        table.insert(ct, '</file>\n')
      else
        table.insert(ct, '<error>見つかりませんでした</error>')
      end
    end
  end
  table.insert(ct, '</entry>')
end

cl=0
for i,v in ipairs(ct) do cl=cl+#v end
mg.write(Response(200, 'text/xml', 'utf-8', cl) ..'\r\n')
if mg.request_info.request_method~='HEAD' then
  for i,v in ipairs(ct) do mg.write(v) end
end

-- 未作成のサムネを作成
for i,v in ipairs(autoMakeThumbs or {}) do
  MakeThumbs(v)
end
