package util.game;

import java.io.IOException;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import util.configuration.RemoteResourceLoader;
import util.gdl.grammar.Gdl;
import util.kif.KifReader;
import external.JSON.JSONArray;
import external.JSON.JSONException;
import external.JSON.JSONObject;

/**
 * Remote game repositories provide access to game resources stored on game
 * repository servers on the web. These require a network connection to work.
 * 
 * @author Sam
 */
public final class RemoteGameRepository extends GameRepository {
    private final String theRepoURL;
    
    public RemoteGameRepository(String theURL) {
        theRepoURL = theURL;
    }
    
    protected Set<String> getUncachedGameKeys() {
        try {
            Set<String> theGameKeys = new HashSet<String>();
            JSONArray theArray = RemoteResourceLoader.loadJSONArray(theRepoURL + "/games/");
            
            for(int i = 0; i < theArray.length(); i++) {
                theGameKeys.add(theArray.getString(i));
            }
            
            return theGameKeys;
        } catch (Exception e) {
            // TODO: Log this exception somewhere?
            return null;
        }
    }
    
    protected Game getUncachedGame(String theKey) {
        try {
            JSONObject theMetadata = getGameMetadataFromRepository(theKey);
            
            String theName = null;
            try {
                theName = theMetadata.getString("gameName");
            } catch(JSONException e) {}
            String theRepositoryURL = theRepoURL + "/games/" + theKey + "/";
            String theDescription = getGameResourceFromMetadata(theKey, theMetadata, "description");                
            String theStylesheet = getGameResourceFromMetadata(theKey, theMetadata, "stylesheet");
            List<Gdl> theRules = getGameRulesheetFromMetadata(theKey, theMetadata);
            
            return new Game(theKey, theName, theDescription, theRepositoryURL, theStylesheet, theRules);
        } catch(IOException e) {
            return null;
        }
    }
    
    // ============================================================================================
    private JSONObject getGameMetadataFromRepository(String theGame) throws IOException {
        return RemoteResourceLoader.loadJSON(theRepoURL + "/games/" + theGame + "/");
    }
    
    private String getGameResourceFromMetadata(String theGame, JSONObject theMetadata, String theResource) {
        try {
            String theResourceFile = theMetadata.getString(theResource);
            return RemoteResourceLoader.loadRaw(theRepoURL + "/games/" + theGame + "/" + theResourceFile);
        } catch (Exception e) {
            return null;
        }
    } 
        
    private List<Gdl> getGameRulesheetFromMetadata(String theGame, JSONObject theMetadata) {
        try {
            String theRulesheetFile = theMetadata.getString("rulesheet");
            return KifReader.readURL(theRepoURL + "/games/" + theGame + "/" + theRulesheetFile);
        } catch (Exception e) {
            return null;
        }
    } 
}
@@ -1324,37 +1324,299 @@
 Key) %7B%0D%0A        
-try %7B
+return loadSingleGame(getGameURL(theKey));%0D%0A    %7D%0D%0A    %0D%0A    public static Game loadSingleGame(String theGameURL) %7B%0D%0A        try %7B%0D%0A            String%5B%5D theSplitURL = theGameURL.split(%22/%22);%0D%0A            String theKey = theSplitURL%5BtheSplitURL.length-1%5D;%0D%0A            
 %0D%0A            JS
@@ -1671,19 +1671,23 @@
 tory(the
-Key
+GameURL
 );%0D%0A    
@@ -1870,72 +1870,8 @@
     
-String theRepositoryURL = theRepoURL + %22/games/%22 + theKey + %22/%22;
 %0D%0A  
@@ -1927,35 +1927,39 @@
 FromMetadata(the
-Key
+GameURL
 , theMetadata, %22
@@ -2048,35 +2048,39 @@
 FromMetadata(the
-Key
+GameURL
 , theMetadata, %22
@@ -2155,27 +2155,31 @@
 Metadata(the
-Key
+GameURL
 , theMetadat
@@ -2261,26 +2261,20 @@
 ion, the
-Repository
+Game
 URL, the
@@ -2358,39 +2358,51 @@
 null;%0D%0A        %7D
+        
 %0D%0A    %7D
+    
 %0D%0A    %0D%0A    // =
@@ -2506,16 +2506,141 @@
 private 
+String getGameURL(String theGame) %7B%0D%0A        return theRepoURL + %22/games/%22 + theGame + %22/%22;%0D%0A    %7D%0D%0A    %0D%0A    private static 
 JSONObje
@@ -2686,16 +2686,19 @@
  theGame
+URL
 ) throws
@@ -2765,43 +2765,15 @@
 (the
-RepoURL + %22/games/%22 + theGame + %22/%22
+GameURL
 );%0D%0A
@@ -2789,32 +2789,39 @@
   %0D%0A    private 
+static 
 String getGameRe
@@ -2845,32 +2845,35 @@
 a(String theGame
+URL
 , JSONObject the
@@ -3049,43 +3049,15 @@
 (the
-RepoURL + %22/games/%22 + theGame + %22/%22
+GameURL
  + t
@@ -3174,16 +3174,23 @@
 private 
+static 
 List%3CGdl
@@ -3234,16 +3234,19 @@
  theGame
+URL
 , JSONOb
@@ -3400,43 +3400,15 @@
 (the
-RepoURL + %22/games/%22 + theGame + %22/%22
+GameURL
  + t

Add a stand-alone way to load a Game object based on its URL, independent of the fancy GameRepository object.