content: package rabbitescape.ui.swing;
  
  import java.net.UnknownHostException;
  import java.util.ArrayList;
  import java.util.regex.Pattern;
  
  import static rabbitescape.engine.i18n.Translation.t;
  
  /**
   * @brief retrieval and parsing. no swing.
   */
  public class GitHubClient implements GitHubPageFetchNotifier
  {
      public final String baseURL =
          "https://api.github.com/repos/andybalaam/rabbit-escape/issues";
      public final String acceptHeader = "Accept: application/vnd.github.v3+json";
      private ArrayList<GitHubIssue> issues = null;
      private String errMsg = "";
      private int page = 1;
      /** < .../issues?page=number */
      private boolean gotAllPages = false;
  
      /** < @brief do not query for more pages of issues */
  
      public GitHubClient()
      {
      }
  
      public void initialise()
      {
          String jsonIssues = apiCall( "" );
          issues = parseIssues( jsonIssues );
      }
  
      public void fetchComments( GitHubIssue ghi )
      {
          String jsonComments = apiCall( "/" + ghi.getNumber() + "/comments" );
          String[] commentBodies = GitHubJsonTools
              .getStringValuesFromArrayOfObjects( jsonComments, "body" );
  
          for ( int i = 0; i < commentBodies.length; i++ )
          {
              ghi.addToBody( commentBodies[i] );
          }
      }
  
      public String getError()
      {
          return errMsg;
      }
  
      /**
       * @param GitHubPageFetcher
       *            required in case more issues need fetching. This method can
       *            make a call back to the UI. This is necessary as it may be
       *            time consuming: the user needs a progress bar or something.
       */
      public GitHubIssue getIssue( int index, GitHubPageFetcher ghpf )
      {
          if ( null == issues || index < 0 )
          {
              return null;
          }
          if ( index >= issues.size() )
          {
              if ( gotAllPages )
              {
                  return null;
              }
              ghpf.notifyAndFetch( baseURL + "?page=" + ( ++page ),
                  acceptHeader,
                  t( "Fetching more issues." ),
                  this );
              return null; // user waits and requests again
          }
          return issues.get( index );
      }
  
      public int getIndexOfNumber( int issueNumber )
      {
          for ( int i = 0; i < issues.size(); i++ )
          {
              GitHubIssue ghi = issues.get( i );
              if ( ghi.getNumber() == issueNumber )
              {
                  return i;
              }
          }
          return -1;
      }
  
      private static ArrayList<GitHubIssue> parseIssues( String json )
      { // / @TODO this is extremely crufty: hacking out most of the URL to split
        // on.
        // This leaves the issue number as the first thing in the string.
          Pattern issuePattern = Pattern.compile(
              "\\{\"url\":\"https://api\\.github\\.com" +
              "/repos/andybalaam/rabbit-escape/issues/" );
          String[] jsonIssuesStrings = issuePattern.split( json );
          ArrayList<GitHubIssue> ret = new ArrayList<GitHubIssue>();
          for ( int i = 0; i < jsonIssuesStrings.length; i++ )
          {
              String jsonIssue = jsonIssuesStrings[i];
              if ( !"0123456789".contains( jsonIssue.substring( 0, 1 ) ) )
              {
                  continue;
              }
  
              GitHubIssue ghi = new GitHubIssue(
                  GitHubJsonTools.getIntValue( jsonIssue, "number" ),
                  GitHubJsonTools.getStringValue( jsonIssue, "title" ),
                  GitHubJsonTools.getStringValue( jsonIssue, "body" ),
                  GitHubJsonTools.getStringValuesFromArrayOfObjects( jsonIssue,
                      "labels.name" )
                  );
              ret.add( ghi );
          }
          return ret;
      }
  
      private String apiCall( String endURL )
      {
          try
          {
              return HttpTools.get( baseURL + endURL, acceptHeader );
          }
          catch ( UnknownHostException eUH )
          {
              errMsg = t( "Can't reach github.com." );
          }
          catch ( Exception e )
          {
              e.printStackTrace();
          }
          return null;
      }
  
      @Override
      public void setPage( String page )
      {
          ArrayList<GitHubIssue> extra = parseIssues( page );
          issues.addAll( extra );
          if ( 0 == extra.size() )
          {
              gotAllPages = true; // Github has no more to give
          }
      }
  }
  