public String extractVideoUrl() throws IOException, InterruptedException {
    id = extractId(youtubeUrl);
    if (StringUtils.isBlank(id)) {
      return "";
    }
    LOGGER.debug("Parsed youtube id: " + id);

    VideoQuality desiredQuality = itagMap.get(extractQuality(youtubeUrl));
    if (desiredQuality == null) {
      // try to pick the quality via settings
      switch (MovieModuleManager.MOVIE_SETTINGS.getTrailerQuality()) {
        case HD_1080:
          desiredQuality = VideoQuality.p1080;
          break;

        case HD_720:
          desiredQuality = VideoQuality.p720;
          break;

        default:
          desiredQuality = VideoQuality.p480;
          break;
      }
    }

    // get the info page
    try {
      Url jsonConfigUrl = new Url(youtubeUrl + "&spf=prefetch");
      StringWriter writer = new StringWriter();
      IOUtils.copy(jsonConfigUrl.getInputStream(), writer, "UTF-8");
      jsonConfiguration = writer.toString();

      List<VideoDownload> downloads = extractJsonInfo();
      // return the first; this is either the desired quality or anything similar
      if (!downloads.isEmpty()) {
        // get the desired quality
        for (VideoDownload dl : downloads) {
          if (dl.vq == desiredQuality) {
            return URLDecoder.decode(dl.url.toExternalForm(), "UTF-8");
          }
        }

        // still not found any useful link.. try to get the best one
        for (VideoDownload dl : downloads) {
          return URLDecoder.decode(dl.url.toExternalForm(), "UTF-8");
        }
      }
    } catch (MalformedURLException e) {
      throw e;
    } catch (Exception e) {
      return "";
    }

    return "";
  }
  /**
   * Instantiates a new movie extended search
   *
   * @param model the model
   */
  public MovieExtendedSearchPanel(MovieSelectionModel model) {
    super();
    setOpaque(false);
    shadowAlpha = 100;
    arcs = new Dimension(10, 10);

    this.movieSelectionModel = model;
    Map<MovieSearchOptions, Object> savedSearchOptions =
        MovieModuleManager.MOVIE_SETTINGS.getUiFilters();

    // add a dummy mouse listener to prevent clicking through
    addMouseListener(new MouseAdapter() {});

    setLayout(
        new FormLayout(
            new ColumnSpec[] {
              FormFactory.RELATED_GAP_COLSPEC,
              FormFactory.DEFAULT_COLSPEC,
              FormFactory.RELATED_GAP_COLSPEC,
              ColumnSpec.decode("default:grow"),
              FormFactory.RELATED_GAP_COLSPEC,
              ColumnSpec.decode("default:grow"),
              FormFactory.UNRELATED_GAP_COLSPEC,
            },
            new RowSpec[] {
              FormFactory.RELATED_GAP_ROWSPEC,
              FormFactory.DEFAULT_ROWSPEC,
              FormFactory.NARROW_LINE_GAP_ROWSPEC,
              FormFactory.DEFAULT_ROWSPEC,
              FormFactory.DEFAULT_ROWSPEC,
              FormFactory.DEFAULT_ROWSPEC,
              FormFactory.DEFAULT_ROWSPEC,
              FormFactory.DEFAULT_ROWSPEC,
              FormFactory.DEFAULT_ROWSPEC,
              FormFactory.DEFAULT_ROWSPEC,
              FormFactory.DEFAULT_ROWSPEC,
              FormFactory.DEFAULT_ROWSPEC,
              FormFactory.DEFAULT_ROWSPEC,
              FormFactory.DEFAULT_ROWSPEC,
              FormFactory.DEFAULT_ROWSPEC,
              FormFactory.DEFAULT_ROWSPEC,
              FormFactory.DEFAULT_ROWSPEC,
              FormFactory.DEFAULT_ROWSPEC,
              FormFactory.DEFAULT_ROWSPEC,
              FormFactory.DEFAULT_ROWSPEC,
              FormFactory.NARROW_LINE_GAP_ROWSPEC,
              FormFactory.DEFAULT_ROWSPEC,
              FormFactory.NARROW_LINE_GAP_ROWSPEC,
              FormFactory.DEFAULT_ROWSPEC,
              FormFactory.NARROW_LINE_GAP_ROWSPEC,
              FormFactory.DEFAULT_ROWSPEC,
              FormFactory.UNRELATED_GAP_ROWSPEC,
            }));

    JLabel lblFilterBy =
        new JLabel(BUNDLE.getString("movieextendedsearch.filterby")); // $NON-NLS-1$
    setComponentFont(lblFilterBy);
    add(lblFilterBy, "2, 2, 3, 1");

    cbFilterDuplicates = new JCheckBox("");
    cbFilterDuplicates.setUI(CHECKBOX_UI); // $hide$
    cbFilterDuplicates.setSelected(savedSearchOptions.containsKey(MovieSearchOptions.DUPLICATES));
    cbFilterDuplicates.setAction(actionFilter);
    add(cbFilterDuplicates, "2, 4");

    JLabel lblShowDuplicates =
        new JLabel(BUNDLE.getString("movieextendedsearch.duplicates")); // $NON-NLS-1$
    setComponentFont(lblShowDuplicates);
    add(lblShowDuplicates, "4, 4, right, default");

    cbFilterWatched = new JCheckBox("");
    cbFilterWatched.setUI(CHECKBOX_UI); // $hide$
    cbFilterWatched.setSelected(savedSearchOptions.containsKey(MovieSearchOptions.WATCHED));
    cbFilterWatched.setAction(actionFilter);
    add(cbFilterWatched, "2, 5");

    JLabel lblWatchedFlag =
        new JLabel(BUNDLE.getString("movieextendedsearch.watched")); // $NON-NLS-1$
    setComponentFont(lblWatchedFlag);
    add(lblWatchedFlag, "4, 5, right, default");

    cbWatched = new SmallComboBox(WatchedFlag.values());
    setComponentFont(cbWatched);
    cbWatched.setAction(actionFilter);
    add(cbWatched, "6, 5, fill, default");

    cbFilterGenre = new JCheckBox("");
    cbFilterGenre.setUI(CHECKBOX_UI); // $hide$
    cbFilterGenre.setSelected(savedSearchOptions.containsKey(MovieSearchOptions.GENRE));
    cbFilterGenre.setAction(actionFilter);
    add(cbFilterGenre, "2, 6");

    JLabel lblGenre = new JLabel(BUNDLE.getString("movieextendedsearch.genre")); // $NON-NLS-1$
    setComponentFont(lblGenre);
    add(lblGenre, "4, 6, right, default");

    cbGenre = new SmallComboBox(MediaGenres.values());
    setComponentFont(cbGenre);
    cbGenre.setAction(actionFilter);
    add(cbGenre, "6, 6, fill, default");

    cbFilterCertification = new JCheckBox("");
    cbFilterCertification.setUI(CHECKBOX_UI); // $hide$
    cbFilterCertification.setSelected(
        savedSearchOptions.containsKey(MovieSearchOptions.CERTIFICATION));
    cbFilterCertification.setAction(actionFilter);
    add(cbFilterCertification, "2, 7");

    lblCertification = new JLabel(BUNDLE.getString("metatag.certification")); // $NON-NLS-1$
    setComponentFont(lblCertification);
    add(lblCertification, "4, 7, right, default");

    cbCertification = new SmallComboBox();
    setComponentFont(cbCertification);
    cbCertification.setAction(actionFilter);
    add(cbCertification, "6, 7, fill, default");

    cbFilterYear = new JCheckBox("");
    cbFilterYear.setUI(CHECKBOX_UI); // $hide$
    cbFilterYear.setSelected(savedSearchOptions.containsKey(MovieSearchOptions.YEAR));
    cbFilterYear.setAction(actionFilter);
    add(cbFilterYear, "2, 8");

    lblYear = new JLabel(BUNDLE.getString("metatag.year")); // $NON-NLS-1$
    setComponentFont(lblYear);
    add(lblYear, "4, 8, right, default");

    int year = Calendar.getInstance().get(Calendar.YEAR);
    spYear = new JSpinner();
    setComponentFont(spYear);
    spYear.setUI(new SmallSpinnerUI());
    spYear.setModel(new SpinnerNumberModel(year, 0, 3000, 1));
    spYear.setEditor(new JSpinner.NumberEditor(spYear, "#"));
    spYear.addChangeListener(
        new ChangeListener() {
          @Override
          public void stateChanged(ChangeEvent e) {
            actionFilter.actionPerformed(null);
          }
        });
    add(spYear, "6, 8");

    cbFilterCast = new JCheckBox("");
    cbFilterCast.setUI(CHECKBOX_UI); // $hide$
    cbFilterCast.setSelected(savedSearchOptions.containsKey(MovieSearchOptions.CAST));
    cbFilterCast.setAction(actionFilter);
    add(cbFilterCast, "2, 9");

    JLabel lblCastMember = new JLabel(BUNDLE.getString("movieextendedsearch.cast")); // $NON-NLS-1$
    setComponentFont(lblCastMember);
    add(lblCastMember, "4, 9, right, default");

    tfCastMember = new JTextField();
    setComponentFont(tfCastMember);
    tfCastMember.setBorder(new SmallTextFieldBorder());
    add(tfCastMember, "6, 9, fill, default");
    tfCastMember.setColumns(10);
    tfCastMember
        .getDocument()
        .addDocumentListener(
            new DocumentListener() {
              public void changedUpdate(DocumentEvent e) {
                actionFilter.actionPerformed(null);
              }

              public void insertUpdate(DocumentEvent e) {
                actionFilter.actionPerformed(null);
              }

              public void removeUpdate(DocumentEvent e) {
                actionFilter.actionPerformed(null);
              }
            });

    cbFilterTag = new JCheckBox("");
    cbFilterTag.setUI(CHECKBOX_UI); // $hide$
    cbFilterTag.setSelected(savedSearchOptions.containsKey(MovieSearchOptions.TAG));
    cbFilterTag.setAction(actionFilter);
    add(cbFilterTag, "2, 10");

    JLabel lblTag = new JLabel(BUNDLE.getString("movieextendedsearch.tag")); // $NON-NLS-1$
    setComponentFont(lblTag);
    add(lblTag, "4, 10, right, default");

    cbTag = new SmallComboBox();
    setComponentFont(cbTag);
    cbTag.setAction(actionFilter);

    add(cbTag, "6, 10, fill, default");

    cbFilterMovieset = new JCheckBox("");
    cbFilterMovieset.setUI(CHECKBOX_UI); // $hide$
    cbFilterMovieset.setSelected(savedSearchOptions.containsKey(MovieSearchOptions.MOVIESET));
    cbFilterMovieset.setAction(actionFilter);
    add(cbFilterMovieset, "2, 11");

    JLabel lblMoviesInMovieset =
        new JLabel(BUNDLE.getString("movieextendedsearch.movieset")); // $NON-NLS-1$
    setComponentFont(lblMoviesInMovieset);
    add(lblMoviesInMovieset, "4, 11, right, default");

    cbMovieset = new SmallComboBox(MovieInMovieSet.values());
    setComponentFont(cbMovieset);
    cbMovieset.setAction(actionFilter);
    add(cbMovieset, "6, 11, fill, default");

    cbFilterVideoFormat = new JCheckBox("");
    cbFilterVideoFormat.setUI(CHECKBOX_UI); // $hide$
    cbFilterVideoFormat.setSelected(
        savedSearchOptions.containsKey(MovieSearchOptions.VIDEO_FORMAT));
    cbFilterVideoFormat.setAction(actionFilter);
    add(cbFilterVideoFormat, "2, 12");

    JLabel lblVideoFormat = new JLabel(BUNDLE.getString("metatag.resolution")); // $NON-NLS-1$
    setComponentFont(lblVideoFormat);
    add(lblVideoFormat, "4, 12, right, default");

    cbVideoFormat = new SmallComboBox(getVideoFormats());
    setComponentFont(cbVideoFormat);
    cbVideoFormat.setAction(actionFilter);
    add(cbVideoFormat, "6, 12, fill, default");

    cbFilterVideoCodec = new JCheckBox("");
    cbFilterVideoCodec.setUI(CHECKBOX_UI); // $hide$
    cbFilterVideoCodec.setSelected(savedSearchOptions.containsKey(MovieSearchOptions.VIDEO_CODEC));
    cbFilterVideoCodec.setAction(actionFilter);
    add(cbFilterVideoCodec, "2, 13");

    JLabel lblVideoCodec = new JLabel(BUNDLE.getString("metatag.videocodec")); // $NON-NLS-1$
    setComponentFont(lblVideoCodec);
    add(lblVideoCodec, "4, 13, right, default");

    cbVideoCodec = new SmallComboBox();
    setComponentFont(cbVideoCodec);
    cbVideoCodec.setAction(actionFilter);
    add(cbVideoCodec, "6, 13, fill, default");

    cbFilterAudioCodec = new JCheckBox("");
    cbFilterAudioCodec.setUI(CHECKBOX_UI); // $hide$
    cbFilterAudioCodec.setSelected(savedSearchOptions.containsKey(MovieSearchOptions.AUDIO_CODEC));
    cbFilterAudioCodec.setAction(actionFilter);
    add(cbFilterAudioCodec, "2, 14");

    JLabel lblAudioCodec = new JLabel(BUNDLE.getString("metatag.audiocodec")); // $NON-NLS-1$
    setComponentFont(lblAudioCodec);
    add(lblAudioCodec, "4, 14, right, default");

    cbAudioCodec = new SmallComboBox();
    setComponentFont(cbAudioCodec);
    cbAudioCodec.setAction(actionFilter);
    add(cbAudioCodec, "6, 14, fill, default");

    cbFilterDatasource = new JCheckBox("");
    cbFilterDatasource.setUI(CHECKBOX_UI); // $hide$
    cbFilterDatasource.setSelected(savedSearchOptions.containsKey(MovieSearchOptions.DATASOURCE));
    cbFilterDatasource.setAction(actionFilter);
    add(cbFilterDatasource, "2, 15");

    JLabel lblDatasource = new JLabel(BUNDLE.getString("metatag.datasource")); // $NON-NLS-1$
    setComponentFont(lblDatasource);
    add(lblDatasource, "4, 15, right, default");

    cbDatasource = new SmallComboBox();
    setComponentFont(cbDatasource);
    cbDatasource.setAction(actionFilter);
    add(cbDatasource, "6, 15, fill, default");

    cbFilterMediaSource = new JCheckBox("");
    cbFilterMediaSource.setUI(CHECKBOX_UI); // $hide$
    cbFilterMediaSource.setSelected(
        savedSearchOptions.containsKey(MovieSearchOptions.MEDIA_SOURCE));
    cbFilterMediaSource.addActionListener(actionFilter);
    add(cbFilterMediaSource, "2, 16");

    JLabel lblMediaSource = new JLabel(BUNDLE.getString("metatag.source")); // $NON-NLS-1$
    setComponentFont(lblMediaSource);
    add(lblMediaSource, "4, 16, right, default");

    cbMediaSource = new SmallComboBox(MovieMediaSource.values());
    setComponentFont(cbMediaSource);
    cbMediaSource.setAction(actionFilter);
    add(cbMediaSource, "6, 16, fill, default");

    cbFilterMissingMetadata = new JCheckBox("");
    cbFilterMissingMetadata.setUI(CHECKBOX_UI); // $hide$
    cbFilterMissingMetadata.setSelected(
        savedSearchOptions.containsKey(MovieSearchOptions.MISSING_METADATA));
    cbFilterMissingMetadata.setAction(actionFilter);
    add(cbFilterMissingMetadata, "2, 17");

    JLabel lblMissingMetadata =
        new JLabel(BUNDLE.getString("movieextendedsearch.missingmetadata")); // $NON-NLS-1$
    setComponentFont(lblMissingMetadata);
    add(lblMissingMetadata, "4, 17, right, default");

    cbFilterMissingArtwork = new JCheckBox("");
    cbFilterMissingArtwork.setUI(CHECKBOX_UI); // $hide$
    cbFilterMissingArtwork.setSelected(
        savedSearchOptions.containsKey(MovieSearchOptions.MISSING_ARTWORK));
    cbFilterMissingArtwork.setAction(actionFilter);
    add(cbFilterMissingArtwork, "2, 18");

    JLabel lblMissingArtwork =
        new JLabel(BUNDLE.getString("movieextendedsearch.missingartwork")); // $NON-NLS-1$
    setComponentFont(lblMissingArtwork);
    add(lblMissingArtwork, "4, 18, right, default");

    cbFilterMissingSubtitles = new JCheckBox("");
    cbFilterMissingSubtitles.setUI(CHECKBOX_UI); // $hide$
    cbFilterMissingSubtitles.setSelected(
        savedSearchOptions.containsKey(MovieSearchOptions.MISSING_SUBTITLES));
    cbFilterMissingSubtitles.setAction(actionFilter);
    add(cbFilterMissingSubtitles, "2, 19");

    JLabel lblMissingSubtitles =
        new JLabel(BUNDLE.getString("movieextendedsearch.missingsubtitles")); // $NON-NLS-1$
    setComponentFont(lblMissingSubtitles);
    add(lblMissingSubtitles, "4, 19, right, default");

    cbFilterNewMovies = new JCheckBox("");
    cbFilterNewMovies.setUI(CHECKBOX_UI); // $hide$
    cbFilterNewMovies.setSelected(savedSearchOptions.containsKey(MovieSearchOptions.NEW_MOVIES));
    cbFilterNewMovies.setAction(actionFilter);
    add(cbFilterNewMovies, "2, 20");

    lblNewMovies = new JLabel(BUNDLE.getString("movieextendedsearch.newmovies")); // $NON-NLS-1$
    setComponentFont(lblNewMovies);
    add(lblNewMovies, "4, 20, right, default");

    JSeparator separator = new JSeparator();
    add(separator, "2, 22, 5, 1");

    JLabel lblSortBy = new JLabel(BUNDLE.getString("movieextendedsearch.sortby")); // $NON-NLS-1$
    setComponentFont(lblSortBy);
    add(lblSortBy, "2, 24, 3, 1");

    cbSortColumn = new SmallComboBox(SortColumn.values());
    setComponentFont(cbSortColumn);
    cbSortColumn.setAction(actionSort);
    add(cbSortColumn, "2, 26, 3, 1, fill, default");

    cbSortOrder = new SmallComboBox(SortOrder.values());
    setComponentFont(cbSortOrder);
    cbSortOrder.setAction(actionSort);
    add(cbSortOrder, "6, 26, fill, default");

    PropertyChangeListener propertyChangeListener =
        new PropertyChangeListener() {
          @Override
          public void propertyChange(PropertyChangeEvent evt) {
            if (evt.getSource() instanceof MovieList && "tag".equals(evt.getPropertyName())) {
              buildAndInstallTagsArray();
            }
            if (evt.getSource() instanceof MovieList
                && "videoCodec".equals(evt.getPropertyName())) {
              buildAndInstallCodecArray();
            }
            if (evt.getSource() instanceof MovieList
                && "audioCodec".equals(evt.getPropertyName())) {
              buildAndInstallCodecArray();
            }
            if (evt.getSource() instanceof MovieSettings
                && "movieDataSource".equals(evt.getPropertyName())) {
              buildAndInstallDatasourceArray();
            }
            if (evt.getSource() instanceof MovieList
                && "certification".equals(evt.getPropertyName())) {
              buildAndInstallCertificationArray();
            }
          }
        };
    movieList.addPropertyChangeListener(propertyChangeListener);
    Settings.getInstance().getMovieSettings().addPropertyChangeListener(propertyChangeListener);
    buildAndInstallTagsArray();
    buildAndInstallCodecArray();
    buildAndInstallDatasourceArray();
    buildAndInstallCertificationArray();
  }