''dsmplayer.wxb''

'show the tag dialog
Sub onShowTags(event As wxCommandEvent)
  Dim sel As Integer = lcMedia.GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED)
  If sel = -1 Then Return

  Dim path As String = lcMedia.GetStringItem(sel, 5) 

  Dim fileFormat As String = getfileFormat(path)
  Dim canWrite As Integer = FALSE
  Select Case fileFormat
  Case "mp3", "ogg", "opus", "flac": canWrite = TRUE 
  End Select

  'use unsorted tags from: https://web.mit.edu/graphics/src/Image-ExifTool-6.99/html/TagNames/ID3.html
  Dim id3Genres[193]
  id3Genres = ["Blues", "Classic Rock", "Country", "Dance", "Disco", "Funk", "Grunge", "Hip-Hop", "Jazz", "Metal", "New Age", "Oldies", "Other", 
    "Pop", "R&B", "Rap", "Reggae", "Rock", "Techno", "Industrial", "Alternative", "Ska", "Death Metal", "Pranks", "Soundtrack", "Euro-Techno", "Ambient", 
    "Trip-Hop", "Vocal", "Jazz+Funk", "Fusion", "Trance", "Classical", "Instrumental", "Acid", "House", "Game", "Sound Clip", "Gospel", "Noise", "Alt. Rock", 
    "Bass", "Soul", "Punk", "Space", "Meditative", "Instrumental Pop", "Instrumental Rock", "Ethnic", "Gothic", "Darkwave", "Techno-Industrial", "Electronic", 
    "Pop-Folk", "Eurodance", "Dream", "Southern Rock", "Comedy", "Cult", "Gangsta Rap", "Top 40", "Christian Rap", "Pop/Funk", "Jungle", "Native American", 
    "Cabaret", "New Wave", "Psychedelic", "Rave", "Showtunes", "Trailer", "Lo-Fi", "Tribal", "Acid Punk", "Acid Jazz", "Polka", "Retro", "Musical", "Rock & Roll", 
    "Hard Rock", "Folk", "Folk-Rock", "National Folk", "Swing", "Fast-Fusion", "Bebop", "Latin", "Revival", "Celtic", "Bluegrass", "Avantgarde", "Gothic Rock", 
    "Progressive Rock", "Psychedelic Rock", "Symphonic Rock", "Slow Rock", "Big Band", "Chorus", "Easy Listening", "Acoustic", "Humour", "Speech", "Chanson", 
    "Opera", "Chamber Music", "Sonata", "Symphony", "Booty Bass", "Primus", "Porn Groove", "Satire", "Slow Jam", "Club", "Tango", "Samba", "Folklore", "Ballad", 
    "Power Ballad", "Rhythmic Soul", "Freestyle", "Duet", "Punk Rock", "Drum Solo", "A Cappella", "Euro-House", "Dance Hall", "Goa", "Drum & Bass", "Club-House", 
    "Hardcore", "Terror", "Indie", "BritPop", "Afro-Punk", "Polsk Punk", "Beat", "Christian Gangsta Rap", "Heavy Metal", "Black Metal", "Crossover", "Contemporary Christian", 
    "Christian Rock", "Merengue", "Salsa", "Thrash Metal", "Anime", "JPop", "Synthpop", "Abstract", "Art Rock", "Baroque", "Bhangra", "Big Beat", 
    "Breakbeat", "Chillout", "Downtempo", "Dub", "EBM", "Eclectic", "Electro", "Electroclash", "Emo", "Experimental", "Garage", "Global", "IDM", "Illbient", 
    "Industro-Goth", "Jam Band", "Krautrock", "Leftfield", "Lounge", "Math Rock", "New Romantic", "Nu-Breakz", "Post-Punk", "Post-Rock", "Psytrance", 
    "Shoegaze", "Space Rock", "Trop Rock", "World Music", "Neoclassical", "Audiobook", "Audio Theatre", "Neue Deutsche Welle", "Podcast", "Indie Rock", 
    "G-Funk", "Dubstep", "Garage Rock", "Psybient", "None"]

  'how to handle wxArrayStringFromArrPtr ?
  'this gives an memory error
'  Dim id3G As wxArrayString = wxArrayStringFromArrPtr(193, id3Genres)
  'this add the array as one item to the arraystring
'  Dim id3G As wxArrayString = wxArrayStringFromArrPtr(1, id3Genres) 

  Dim id3G As wxArrayString = wxArrayString()
  For i = 1 To id3Genres.Count()
    id3G.Add(id3Genres[i])
  Next

  'create the id3 tag dialog
  Dim sd = wxDialog(musicFrame, -1, _("Tag Info for") &" '" &lcMedia.GetStringItem(sel, 1) &"'", wxDefaultPosition, wxSize(800, 600))
  Dim dSizeX = sd.GetClientSizeWidth()
  Dim dSizeY = sd.GetClientSizeHeight()

  Dim sBox As wxStaticBox = wxStaticBox(sd, -1, _("ID3v1 Tag:"), wxPoint(10, 10), wxSize((dSizeX / 3)* 2 - 50, 260))
  Dim bSizeX = sBox.GetClientSizeWidth()

  Dim sText = wxStaticText(sBox, -1, _("Title:"), wxPoint(5, 30))
  Dim title = wxTextCtrl(sBox, -1, "", wxPoint(80, 30), wxSize(bSizeX - 100, 25)): title.SetName("title"): title.Enable(canWrite)
  sText = wxStaticText(sBox, -1, _("Artist:"), wxPoint(5, 60))
  Dim artist = wxTextCtrl(sBox, -1, "", wxPoint(80, 60), wxSize(bSizeX - 100, 25)): artist.SetName("artist"): artist.Enable(canWrite)
  sText = wxStaticText(sBox, -1, _("Album:"), wxPoint(5, 90))
  Dim album = wxTextCtrl(sBox, -1, "", wxPoint(80, 90), wxSize(bSizeX - 100, 25)): album.SetName("album"): album.Enable(canWrite)
  sText = wxStaticText(sBox, -1, _("Year:"), wxPoint(5, 120))
  Dim iYear = wxTextCtrl(sBox, -1, "", wxPoint(80, 120), wxSize(100, 25)): iYear.SetName("year"): iYear.Enable(canWrite)
  sText = wxStaticText(sBox, -1, _("Track:"), wxPoint(bSizeX / 2 + 40, 120))
  Dim track = wxTextCtrl(sBox, -1, "", wxPoint(bSizeX / 2 + 100, 120), wxSize(50, 25)): track.SetName("track"): track.Enable(canWrite)
  sText = wxStaticText(sBox, -1, _("Comment:"), wxPoint(5, 150))
  Dim comment = wxTextCtrl(sBox, -1, "", wxPoint(80, 150), wxSize(bSizeX - 100, 25)): comment.SetName("comment"): comment.Enable(canWrite)
  sText = wxStaticText(sBox, -1, _("Genre:"), wxPoint(5, 180))
  Dim id3Genre = wxComboBox3(sBox, -1, "" , wxPoint(80, 182), wxSize(bSizeX - 100, 25), id3G): id3Genre.SetName("genre"): id3Genre.Enable(canWrite)

  Dim bSave = wxButton(sBox, wxID_OK, _("Save Tags and Close"), wxPoint(80, 220), wxSize((bSizeX - 100)/ 2, 25))
  bSave.Enable(canWrite)
  Dim bRemove = wxButton(sBox, wxID_CLEAR, _("Clear Fields"), wxPoint(80 + (bSizeX - 100)/ 2, 220), wxSize((bSizeX - 100)/ 2, 25))
  bRemove.Enable(canWrite)
  Connect(bRemove, -1, wxEVT_COMMAND_BUTTON_CLICKED, "onClearID3Fields")

  Dim sBox1 As wxStaticBox = wxStaticBox(sd, -1, _("File Info:"), wxPoint(10 + (dSizeX / 3)* 2 - 30, 10), wxSize(dSizeX - ((dSizeX / 3)* 2 - 10), 260))
  sBox1.SetName("box1")
  sText = wxStaticText(sBox1, -1, _("File size:"), wxPoint(5, 30))
  sText = wxStaticText(sBox1, -1, _("Length:"), wxPoint(5, 60))
  sText = wxStaticText(sBox1, -1, _("Bitrate:"), wxPoint(5, 90))
  sText = wxStaticText(sBox1, -1, _("MPEG:"), wxPoint(5, 120))
  sText = wxStaticText(sBox1, -1, _("Format:"), wxPoint(5, 150))
  sText = wxStaticText(sBox1, -1, _("Samplerate:"), wxPoint(5, 180))
  sText = wxStaticText(sBox1, -1, _("Mode:"), wxPoint(5, 210))

  sText = wxStaticText(sd, -1, _("ID3v2/additional Strings:"), wxPoint(5, 290))
  Dim tBox As wxStyledTextCtrl = wxStyledTextCtrl(sd, -1, wxPoint(5, 320), wxSize(dSizeX - 10, 200))
  tBox.SetName("textbox")
  tBox.StyleSetBackground(wxSTC_STYLE_LINENUMBER, wxWHITE)
  tBox.IndicatorSetStyle(0, wxSTC_INDIC_PLAIN)
  tbox.IndicatorSetForeground(0, wxBLACK)
  tbox.SetIndicatorCurrent(0)
'  tBox.SetMarginWidth(wxSTC_MARGIN_NUMBER, 0)
  tBox.SetUseHorizontalScrollBar(FALSE)
  tbox.SetTabWidth(32)
  tBox.StyleSetFont(wxSTC_STYLE_DEFAULT, wxFont(10, wxMODERN, wxNORMAL, wxNORMAL))

  Dim buttonCancel = wxButton(sd, wxID_CANCEL, _("Ok"), wxPoint(0, dSizeY - 25), wxSize((dSizeX), 25))

  'read all tag informations
  Dim buffer, aTitle, aArtist, aAlbum, aYear, aTrack, aComment, aGenre, temp As String
  buffer, atitle, aartist, aalbum, aYear, atrack, acomment, agenre, temp = readID3Tags(path)

'print buffer, atitle, aartist, aalbum, aYear, atrack, acomment, agenre, temp
  If buffer <> "" Then
    Dim info As wxArrayString = wxStringTokenize(buffer, " ")
    If info.Count()= 6 Then
      sText = wxStaticText(sBox1, -1, info.Item(0), wxPoint(120, 30))
      buffer = getTimeFromString(info.Item(1), TRUE, FALSE)

      sText = wxStaticText(sBox1, -1, buffer, wxPoint(120, 60))
      sText = wxStaticText(sBox1, -1, info.Item(2), wxPoint(120, 90))
      sText = wxStaticText(sBox1, -1, info.Item(3), wxPoint(120, 120))
      sText = wxStaticText(sBox1, -1, info.Item(4), wxPoint(120, 150))
      sText = wxStaticText(sBox1, -1, info.Item(5), wxPoint(120, 180))
      sText = wxStaticText(sBox1, -1, info.Item(6), wxPoint(120, 210))
    End If
    info.Clear()
  End If

  'set id3v1 tag informations to the fields
  title.SetValue(aTitle)
  artist.SetValue(aArtist)
  album.SetValue(aalbum)
  iYear.SetValue(aYear)
  track.SetValue(aTrack)
  comment.SetValue(aComment)
  id3Genre.SetValue(aGenre)

  'get the tracktotal information
  Dim at = InStr(temp, "tracktotal")
  Dim total As String = ""

  If at > 0 Then
    total = Trim(temp[at: InStr(at, temp, "\n")])
    info.Remove(total)
    total = total[RInstr(total, Chr(9))+ 1: ]
  Else
    total = "??"
  End If

'we can show the ID3V1 tags as ID3v2 here
'      'if no informations about the idv2tag is in the arraystring and it is in idv1 tag, we can show these as idv2 tag
'      If (info.INDEX("TPE1")= -1) And (artist.GetValue()<> "") Then tBox.AddText("TPE1" &Chr(9) &artist.GetValue() &"\n")
'      If (info.INDEX("TIT2")= -1) And (title.GetValue()<> "") Then tBox.AddText("TIT2" &Chr(9) &title.GetValue() &"\n")
'      If (info.INDEX("TALB")= -1) And (title.GetValue()<> "") Then tBox.AddText("TALB" &Chr(9) &album.GetValue() &"\n")
'      If (info.INDEX("TYER")= -1) And (iYear.GetValue()<> "") Then tBox.AddText("TYER" &Chr(9) &iYear.GetValue() &"\n")
'      If (info.INDEX("TRCK")= -1) And (track.GetValue()<> "") Then tBox.AddText("TRCK" &Chr(9) &track.GetValue() &"/" &total &"\n")
'      If (info.INDEX("TCON")= -1) And (ID3Genre.GetValue()<> "") Then tBox.AddText("TCON" &Chr(9) &ID3Genre.GetValue() &"\n")
'      If (info.INDEX("COMM")= -1) And (comment.GetValue()<> "") Then tBox.AddText("COMM" &Chr(9) &comment.GetValue() &"\n")

  Dim Item, value As String
  Dim flag As Integer = TRUE
  Dim lBegin As Integer

  'split the lines from the buffer to an arraystring
  If InStr(LCase(temp), "error") Then
    tBox.AddText(temp)

  Else
    info = wxStringTokenize(temp, "\n")

    'add idv2 tags and additional informations from file
    For i = 0 To info.Count() - 1
      Item = info.Item(i)

      If (Item[: 7]= "MP3GAIN" Or Item[: 10]= "REPLAYGAIN") Then
        If flag Then
          tBox.AddText("\n" &_("Additional Informations:") &"\n\n")
          lBegin = tBox.GetCurrentLine() - 2
          tBox.IndicatorFillRange(tbox.PositionFromLine(lBegin), tBox.LineLength(lBegin))
          flag = FALSE
        End If
      End If

      value = Item[RInstr(Item, Chr(9))+ 1: ]
      If value <> "" Then tBox.AddText(Item[: InStr(Item, Chr(9)) - 1] &Chr(9) &value &"\n")
    Next

    info.Clear()
  End If
  tBox.SetReadOnly(TRUE)

  'wxID_OK saves the ID3 tag
  If sd.ShowModal()= wxID_OK Then
    writeId3v1Tag(title.GetValue(), artist.GetValue(), album.GetValue(), iYear.GetValue(), track.GetValue(), comment.GetValue(), ID3genre.GetValue(), lcMedia.GetStringItem(sel, 5), TRUE)
  End If

  id3G.Clear()
  ~sd
End Sub


'clear the tag fields
Sub onClearID3Fields(event As wxCommandEvent)
  Dim win = DynamicCast("wxTextCtrl", musicFrame.FindWindowByName("title"))
  win.SetValue("")
  win = DynamicCast("wxTextCtrl", musicFrame.FindWindowByName("artist"))
  win.SetValue("")
  win = DynamicCast("wxTextCtrl", musicFrame.FindWindowByName("album"))
  win.SetValue("")
  win = DynamicCast("wxTextCtrl", musicFrame.FindWindowByName("year"))
  win.SetValue("")
  win = DynamicCast("wxTextCtrl", musicFrame.FindWindowByName("track"))
  win.SetValue("")
  win = DynamicCast("wxTextCtrl", musicFrame.FindWindowByName("comment"))
  win.SetValue("")
  win = DynamicCast("wxComboBox", musicFrame.FindWindowByName("genre"))
  win.SetValue("")
End Sub


Function readID3Tags(path As String)
  Dim info As String = "", aTitle As String = "", aArtist As String = "", aAlbum As String = "", aYear As String = "",
  aTrack As String = "", aComment As String = "", aGenre As String = "", temp As String = ""

  'execute phiola to get the file informations
  Dim infoPrc = New wxProcess(musicFrame)
  infoPrc.Redirect()
  Connect(infoPrc, wxEVT_END_PROCESS, "onEndInfoProcess")

  Dim pid = wxExecute(Chr(34) &phiolaPath &Chr(34) &" info -tags "  &Chr(34) &path &Chr(34) , wxEXEC_ASYNC, infoPrc)
  If pid > 0 Then
    'get the stream
    Dim inStream = infoPrc.GetInputStream()
    Dim buffer As String = ""
    Dim cnt As Integer = 1

    'read the stream
    If inStream And inStream.IsOk() Then
      While !inStream.Eof()
        buffer &= inStream.Read(1)
      Wend

      'split the lines from the buffer to an arraystring
      Dim arr = wxStringTokenize(buffer, "\n")
      For i = arr.Count() - 1 To 0 Step -1
        buffer = arr.Item(i)

        If InStr(buffer, "INFO") Or (buffer = "") Then Continue
        If buffer[: 1]= "[" Then Break

        'first line ist the file info
        If buffer[: 2] = "#1" Then
          'audio formats:
          'WAV format               type
          '32-bit floating-point  = float32
          '32-bit PCM             = int32
          '16-bit PCM             = int16
          '8-bit PCM              = uint8

          Dim at = RInstr(buffer, Chr(34))
          info = buffer[at + 1: InStr(at, buffer, "(") - 1] &buffer[RInstr(buffer, ")")+ 1: ]


        'read id3v1 tag informations 
        Elseif buffer[: 5]= "title" Then
          aTitle = Trim(buffer[6: ])
        Elseif buffer[: 6]= "artist" Then
          aArtist = Trim(buffer[7: ])
        Elseif buffer[: 5] = "album" Then
          aAlbum = Trim(buffer[6: ])
        Elseif buffer[: 4] = "date" Then
          aYear = Trim(buffer[5: ])
        Elseif buffer[: 11] = "tracknumber" Then
          aTrack = Trim(buffer[12: ])
        Elseif buffer[: 7] = "comment" Then
          aComment = Trim(buffer[8: ])
        Elseif buffer[: 5] = "genre" Then
          aGenre = Trim(buffer[6: ])

        Elseif (cnt > 2) And (buffer[: 1] != "[") Then
          'add id3v2 informations to a buffer
          temp &= buffer &"\n"

        Elseif InStr(LCase(buffer), "error") Then
          temp = _("File Error:") &"\n" &_("Cannot read the file information") &": " &buffer[RInstr(buffer, ":")+ 1: ]
        End If

        cnt += 1
      Next
      arr.Clear()

      Return info, aTitle, aArtist, aAlbum, aYear, aTrack, aComment, aGenre, temp
    End If

  Else

    ~infoPrc
    infoPrc = Nothing
  End If
End Function


Sub writeID3v1Tag(title, artist, album, iyear, track, comment, ID3genre, path, ShowMessage)
  Dim FileName As wxFileName = wxFileName(path)
  If !FileName.IsFileWritable() Then
    errCnt += 1

    If errCnt < 20 Then 
      errMsg&= "'" &wxFileNameFromPath(path) &"' " &"is read-only" &"\n"

    Elseif errCnt = 20 Then
      errMsg&= "..."
    End If
    Return
  End If

  infoPrc = New wxProcess(musicFrame)
  infoPrc.Redirect()
  Connect(infoPrc, wxEVT_END_PROCESS, "onEndInfoProcess")

  Dim pid = wxExecute(Chr(34) &phiolaPath &Chr(34) &" tag -m " &Chr(34) &"title=" &title &Chr(34) &
                  " -m " &Chr(34) &"artist=" &artist &Chr(34) &
                  " -m " &Chr(34) &"album=" &album &Chr(34) &
                  " -m " &Chr(34) &"date=" &iYear &Chr(34) &
                  " -m " &Chr(34) &"tracknumber=" &track &Chr(34) &
                  " -m " &Chr(34) &"comment=" &comment &Chr(34) &
                  " -m " &Chr(34) &"genre=" &ID3genre &Chr(34) &
                  " " &Chr(34) &path &Chr(34), wxEXEC_ASYNC, infoPrc)

  If pid Then
    Dim inStream = infoPrc.GetInputStream()

    If inStream And inStream.IsOk() Then
      Dim tStream = wxTextInputStream(inStream, "\t", wxConvUTF8)
      Dim buffer = LCase(tStream.ReadLine())
      While !inStream.Eof()
        tStream.ReadLine()
      Wend

      If InStr(buffer, ("error")) Then
        errCnt += 1
        errMsg&= "'" &wxFileNameFromPath(path) &"' " &"write error" &"\n"
        If ShowMessage Then
          Dim dl = wxGenericMessageDialog(Nothing, _("An error occurred while writing the tags.") &"\n '" &wxFileNameFromPath(path) &"'", _("Attention"), wxOK|wxCENTRE|wxICON_ERROR|wxDIALOG_NO_PARENT|wxSTAY_ON_TOP)
          dl.ShowModal()
          ~dl
        End If
      End If
    End If

  Else
    ~infoPrc
    dl = wxGenericMessageDialog(Nothing, _("Phiola could not be executed."), _("Attention"), wxOK|wxCENTRE|wxICON_ERROR|wxDIALOG_NO_PARENT)
    dl.ShowModal()
    ~dl
  End If
End Sub


'dummy process
'the info process has ended
Sub onEndInfoProcess(event As wxProcessEvent)
  infoPrc = Nothing
  If loadingTimer.IsRunning() Then loadingTimer.Stop()
End Sub
