package com.beaglebuddy.id3.enums.v22;

import java.io.InputStream;
import java.lang.reflect.Constructor;

import com.beaglebuddy.id3.v2.v23.frame_body.*;


/**
 * <table class="logos_width">
 *    <tbody>
 *       <tr>
 *          <td                               ><img src="../../../../resources/id3v2.gif"                     width="56"  height="54"  alt="ID3 logo"        /></td>
 *          <td class="logos_horz_align_right"><img src="../../../../resources/beaglebuddy_software_logo.gif" width="340" height="110" alt="Beaglebuddy logo"/></td>
 *       </tr>
 *    </tbody>
 * </table>
 * The ID3v2.2 Tag Specification defines 63 types of frames.
 * <a href="http://id3.org/id3v2.2.0">ID3v2.2 frame ids</a>.
 */
public enum FrameType
{                                                                                                                                                                    /** frame id - CRA, audio encryption                                      */
   AUDIO_ENCRYPTION                        ("CRA" , "audio encryption"                                     , ID3v22FrameBodyAudioEncryption.class                ),  /** frame id - PIC, attached picture                                      */
   ATTACHED_PICTURE                        ("PIC" , "attached picture"                                     , ID3v22FrameBodyAttachedPicture.class                ),  /** frame id - COM, comments                                              */
   COMMENTS                                ("COM" , "comments"                                             , ID3v22FrameBodyComments.class                       ),  /** frame id - ENC, encryption method registration                        */
   ENCRYPTION_METHOD_REGISTRATION          ("ENCR", "encryption method registration"                       , ID3v22FrameBodyEncryptionMethodRegistration.class   ),  /** frame id - EQU, equalization                                          */
   EQUALIZATION                            ("EQU" , "equalization"                                         , ID3v22FrameBodyEqualization.class                   ),  /** frame id - ETC, event timing codes                                    */
   EVENT_TIMING_CODES                      ("ETC" , "event timing codes"                                   , ID3v22FrameBodyEventTimingCodes.class               ),  /** frame id - GEO, general encapsulated object                           */
   GENERAL_ENCAPSULATED_OBJECT             ("GEO" , "general encapsulated object"                          , ID3v22FrameBodyGeneralEncapsulatedObject.class      ),  /** frame id - IPL, involved people list                                  */
   INVOLVED_PEOPLE_LIST                    ("IPL" , "involved people list"                                 , ID3v22FrameBodyInvolvedPeopleList.class             ),  /** frame id - LNK, linked information                                    */
   LINKED_INFORMATION                      ("LNK" , "linked information"                                   , ID3v22FrameBodyLinkedInformation.class              ),  /** frame id - MCI, music cd identifier                                   */
   MUSIC_CD_IDENTIFIER                     ("MCI" , "music cd identifier"                                  , ID3v22FrameBodyMusicCDIdentifier.class              ),  /** frame id - MLL, mpeg location lookup table                            */
   MPEG_LOCATION_LOOKUP_TABLE              ("MLL" , "mpeg location lookup table"                           , ID3v22FrameBodyMPEGLocationLookupTable.class        ),  /** frame id - CNT, play counter                                          */
   PLAY_COUNTER                            ("CNT" , "play counter"                                         , ID3v22FrameBodyPlayCounter.class                    ),  /** frame id - POP, popularimeter                                         */
   POPULARIMETER                           ("POP" , "popularimeter"                                        , ID3v22FrameBodyPopularimeter.class                  ),  /** frame id - BUF, recommended buffer size                               */
   RECOMMENDED_BUFFER_SIZE                 ("BUF" , "recommended buffer size"                              , ID3v22FrameBodyRecommendedBufferSize.class          ),  /** frame id - RVA, relative volume adjustment                            */
   RELATIVE_VOLUME_ADJUSTMENT              ("RVA" , "relative volume adjustment"                           , ID3v22FrameBodyRelativeVolumeAdjustment.class       ),  /** frame id - REV, reverb                                                */
   REVERB                                  ("REV" , "reverb"                                               , ID3v22FrameBodyReverb.class                         ),  /** frame id - SLY, synchronized lyric/text                               */
   SYNCHRONIZED_LYRIC_TEXT                 ("SLY" , "synchronized lyric/text"                              , ID3v22FrameBodySynchronizedLyricsText.class         ),  /** frame id - STC, synchronized tempo codes                              */
   SYNCHRONIZED_TEMPO_CODES                ("STC" , "synchronized tempo codes"                             , ID3v22FrameBodySynchronizedTempoCodes.class         ),  /** frame id - TAL, album/movie/show title                                */
   ALBUM_TITLE                             ("TAL" , "album/movie/show title"                               , ID3v22FrameBodyTextInformation.class                ),  /** frame id - TBP, bpm (beats per minute)                                */
   BEATS_PER_MINUTE                        ("TBP" , "bpm (beats per minute)"                               , ID3v22FrameBodyTextInformation.class                ),  /** frame id - TCM, composer                                              */
   COMPOSER                                ("TCM" , "composer"                                             , ID3v22FrameBodyTextInformation.class                ),  /** frame id - TCO, content type                                          */
   CONTENT_TYPE                            ("TCO" , "content type"                                         , ID3v22FrameBodyTextInformation.class                ),  /** frame id - TCR, copyright message                                     */
   COPYRIGHT_MESSAGE                       ("TCR" , "copyright message"                                    , ID3v22FrameBodyTextInformation.class                ),  /** frame id - TDA, date                                                  */
   DATE                                    ("TDA" , "date"                                                 , ID3v22FrameBodyTextInformation.class                ),  /** frame id - TDY, playlist delay                                        */
   PLAYLIST_DELAY                          ("TDY" , "playlist delay"                                       , ID3v22FrameBodyTextInformation.class                ),  /** frame id - TEN, encoded by                                            */
   ENCODED_BY                              ("TEN" , "encoded by"                                           , ID3v22FrameBodyTextInformation.class                ),  /** frame id - TXT, lyricist/text writer                                  */
   LYRICIST                                ("TXT" , "lyricist/text writer"                                 , ID3v22FrameBodyTextInformation.class                ),  /** frame id - TFT, file type                                             */
   FILE_TYPE                               ("TFT" , "file type"                                            , ID3v22FrameBodyTextInformation.class                ),  /** frame id - TIM, time                                                  */
   TIME                                    ("TIM" , "time"                                                 , ID3v22FrameBodyTextInformation.class                ),  /** frame id - TT1, content group description                             */
   CONTENT_GROUP_DESCRIPTION               ("TT1" , "content group description"                            , ID3v22FrameBodyTextInformation.class                ),  /** frame id - TT2, title/songname/content description                    */
   SONG_TITLE                              ("TT2" , "title/songname/content description"                   , ID3v22FrameBodyTextInformation.class                ),  /** frame id - TT3, subtitle/description refinement                       */
   SUBTITLE_REFINEMENT                     ("TT3" , "subtitle/description refinement"                      , ID3v22FrameBodyTextInformation.class                ),  /** frame id - TKE, initial key                                           */
   INITIAL_KEY                             ("TKE" , "initial key"                                          , ID3v22FrameBodyTextInformation.class                ),  /** frame id - TLA, language(s)                                           */
   LANGUAGE                                ("TLA" , "language(s)"                                          , ID3v22FrameBodyTextInformation.class                ),  /** frame id - TLE, length of the song (in ms)                            */
   LENGTH                                  ("TLE" , "length of the song (in ms)"                           , ID3v22FrameBodyTextInformation.class                ),  /** frame id - TMT, media type                                            */
   MEDIA_TYPE                              ("TMT" , "media type"                                           , ID3v22FrameBodyTextInformation.class                ),  /** frame id - TOT, original album/movie/show title                       */
   ORIGINAL_ALBUM_TITLE                    ("TOT" , "original album/movie/show title"                      , ID3v22FrameBodyTextInformation.class                ),  /** frame id - TOF, original filename                                     */
   ORIGINAL_FILENAME                       ("TOF" , "original filename"                                    , ID3v22FrameBodyTextInformation.class                ),  /** frame id - TOL, original lyricist(s)/text writer(s)                   */
   ORIGINAL_LYRICIST                       ("TOL" , "original lyricist(s)/text writer(s)"                  , ID3v22FrameBodyTextInformation.class                ),  /** frame id - TOA, original artist(s)/performer(s)                       */
   ORIGINAL_ARTIST                         ("TOA" , "original artist(s)/performer(s)"                      , ID3v22FrameBodyTextInformation.class                ),  /** frame id - TOR, original release year                                 */
   ORIGINAL_RELEASE_YEAR                   ("TOR" , "original release year"                                , ID3v22FrameBodyTextInformation.class                ),  /** frame id - TP1, lead artist(s)/performer(s)/soloist(s)                */
   LEAD_PERFORMER                          ("TP1" , "lead artist(s)/performer(s)/soloist(s)"               , ID3v22FrameBodyTextInformation.class                ),  /** frame id - TP2, band/orchestra/accompaniment                          */
   BAND                                    ("TP2" , "band/orchestra/accompaniment"                         , ID3v22FrameBodyTextInformation.class                ),  /** frame id - TP3, conductor/performer refinement                        */
   CONDUCTOR                               ("TP3" , "conductor/performer refinement"                       , ID3v22FrameBodyTextInformation.class                ),  /** frame id - TP4, interpreted, remixed, or otherwise modified by        */
   INTERPRETED_MODIFIED_BY                 ("TP4" , "interpreted, remixed, or otherwise modified by"       , ID3v22FrameBodyTextInformation.class                ),  /** frame id - TPA, part of a set                                         */
   PART_OF_A_SET                           ("TPA" , "part of a set"                                        , ID3v22FrameBodyTextInformation.class                ),  /** frame id - TPB, publisher                                             */
   PUBLISHER                               ("TPB" , "publisher"                                            , ID3v22FrameBodyTextInformation.class                ),  /** frame id - TRK, track number/position in set                          */
   TRACK_NUMBER                            ("TRK" , "track number/position in set"                         , ID3v22FrameBodyTextInformation.class                ),  /** frame id - TRD, recording dates                                       */
   RECORDING_DATES                         ("TRD" , "recording dates"                                      , ID3v22FrameBodyTextInformation.class                ),  /** frame id - TSI, size of the audio portion of the .mp3 file (in bytes) */
   SIZE                                    ("TSI" , "size of the audio portion of the .mp3 file (in bytes)", ID3v22FrameBodyTextInformation.class                ),  /** frame id - TRC, isrc (international standard recording code)          */
   INTERNATIONAL_STANDARD_RECORDING_CODE   ("TRC" , "isrc (international standard recording code)"         , ID3v22FrameBodyTextInformation.class                ),  /** frame id - TSS, software/hardware and settings used for encoding      */
   SOFTWARE_HARDWARE_ENCODING_SETTINGS     ("TSS" , "software/hardware and settings used for encoding"     , ID3v22FrameBodyTextInformation.class                ),  /** frame id - TYE, year the song was recorded                            */
   YEAR                                    ("TYE" , "year the song was recorded"                           , ID3v22FrameBodyTextInformation.class                ),  /** frame id - TXX, user defined text information frame                   */
   USER_DEFINED_TEXT_INFORMATION           ("TXX" , "user defined text information frame"                  , ID3v22FrameBodyUserDefinedTextInformation.class     ),  /** frame id - UFI, unique file identifier                                */
   UNIQUE_FILE_IDENTIFIER                  ("UFI" , "unique file identifier"                               , ID3v22FrameBodyUniqueFileIdentifier.class           ),  /** frame id - USL, unsychronized lyrics/text transcription               */
   UNSYCHRONIZED_LYRICS                    ("USL" , "unsychronized lyrics/text transcription"              , ID3v22FrameBodyUnsynchronizedLyrics.class           ),  /** frame id - WCM, commercial information                                */
   COMMERCIAL_INFORMATION                  ("WCM" , "commercial information"                               , ID3v22FrameBodyURLLink.class                        ),  /** frame id - WCP, copyright/legal information                           */
   COPYRIGHT_LEGAL_INFORMATION             ("WCP" , "copyright/legal information"                          , ID3v22FrameBodyURLLink.class                        ),  /** frame id - WAF, official audio file webpage                           */
   OFFICIAL_AUDIO_FILE_WEBPAGE             ("WAF" , "official audio file webpage"                          , ID3v22FrameBodyURLLink.class                        ),  /** frame id - WAR, official artist/performer webpage                     */
   OFFICIAL_ARTIST_WEBPAGE                 ("WAR" , "official artist/performer webpage"                    , ID3v22FrameBodyURLLink.class                        ),  /** frame id - WAS, official audio source webpage                         */
   OFFICIAL_AUDIO_SOURCE_WEBPAGE           ("WAS" , "official audio source webpage"                        , ID3v22FrameBodyURLLink.class                        ),  /** frame id - WPB, publishers official webpage                           */
   PUBLISHERS_OFFICIAL_WEBPAGE             ("WPB" , "publishers official webpage"                          , ID3v22FrameBodyURLLink.class                        ),  /** frame id - WXX, user defined url link                                 */
   USER_DEFINED_URL_LINK_FRAME             ("WXX" , "user defined url link"                                , ID3v22FrameBodyUserDefinedURLLink.class             );

   // class members
                                                 /** length of ID3v2.2 frame ids */
   public static final int FRAME_ID_LENGTH = 3;

   // data members
   private String         id;                    // c character id
   private String         description;           // description of the frame type
   private Class<?>       frameBodyClass;        // class used to implement the frame's body
   private Constructor<?> frameBodyConstructor;  // frame body class's constructor used to parse the frame body from an .mp3 file



   /**
    * constructor.
    * @param id                     3 character ID3v2.2 frame id.
    * @param description            description of the frame type.
    * @param frameBodyClass         class used to implement the frame's body.
    */
   private FrameType(String id, String description, Class<?> frameBodyClass)
   {
      this.id             = id;
      this.description    = description;
      this.frameBodyClass = frameBodyClass;

      try
      {
         // the ID3v22FrameBodyTextInformation and ID3v22FrameBodyURLLink classes implement multiple ID3v2.2 frame types and therefore need a frame id when parsing
         // their frame body from an .mp3 file.
         if (frameBodyClass == ID3v22FrameBodyTextInformation.class || frameBodyClass == ID3v22FrameBodyURLLink.class)
            this.frameBodyConstructor = frameBodyClass.getConstructor(new Class<?>[] {InputStream.class, FrameType.class, int.class});
         else
            this.frameBodyConstructor = frameBodyClass.getConstructor(new Class<?>[] {InputStream.class,                  int.class});
      }
      catch (NoSuchMethodException ex)
      {
         // this can never happen
         ex.printStackTrace();
      }
   }

   /**
    * gets the name of the frame type.
    * @return the name of the frame type.
    */
   public String getName()
   {
      return super.toString();
   }

   /**
    * gets the ID3v2.2 frame id.
    * @return the ID3v2.2 frame id.
    */
   public String getId()
   {
      return id;
   }

   /**
    * gets the description of the frame type.
    * @return the description of the frame type.
    */
   public String getDescription()
   {
      return description;
   }

   /**
    * gets the class used to implement the frame's body.
    * @return the class used to implement the frame's body.
    */
   public Class<?> getFrameBodyClass()
   {
      return frameBodyClass;
   }

   /**
    * gets the constructor for the frame body's class used to parse the frame's body from an .mp3 file.
    * @return the frame body class's constructor used to parse an existing frame body from an .mp3 file.
    */
   public Constructor<?> getFrameBodyConstructor()
   {
      return frameBodyConstructor;
   }

   /**
    * convert a string value to its corresponding frame type enum.
    * @return the FrameType enum corresponding to the string value.
    * @param frameId  string value to be converted to a FrameType enum.
    * @throws IllegalArgumentException   if the integral value does not correspond to a valid FrameType.
    */
   public static FrameType getFrameType(String frameId) throws IllegalArgumentException
   {
      for (FrameType ft : FrameType.values())
         if (frameId.equals(ft.getId()))
            return ft;
      throw new IllegalArgumentException("Invalid ID3v2.2 frame type " + frameId + ".");
   }

   /**
    * gets  a string representation of the frame type enum.
    * @return a string representation of the frame type enum.
    */
   public String toString()
   {
      return id + ": " + getName() + " - " + description;
   }
}
