import java.io.*;

class hello extends ActiveCacheInterface {
  protected static String ServerName = "http://www.cs.wisc.edu/~kbeach/wisweb/";

  // the main function of the applet
  public static int FromCache(String User_HTTP_Request,
                        String Client_IP_Address,
                        String Client_Name,
                        int Cache_File,
                        int New_File) {
    String line;
    String prefs;
    String userId;

    try {
      // get the userId from the client request
      userId = getUserId(User_HTTP_Request);
      if (userId == "") {
        // there is not userId specified in the client request
        // send the preference page where user can select his/her preferences
        sendPrefsPage();
      }
      else {
        // check the userId, if this userId does not exist in database
        // also send the preference page
        if ((prefs = getPrefs(userId))=="ERROR"){
          sendPrefsPage();
        }
        // otherwise, we create the new page based on the user preference
        else {
          createPage(New_File, prefs);
        }
      }
      // let the proxy return the new page
      return 1;
    }
    catch (Exception e) {
      return -1;
    }
  }

  // Extract the userId from the HTTP request sent by client
  public static String getUserId(String HTTP_Request){
    String userId="";
    String line;
    try{
          int start, end;
          start = HTTP_Request.indexOf("Cookie: ");
          // if there is no cookie header in client request, return null
          if (start == -1)
          return userId;
          start = HTTP_Request.indexOf("userId=",start);
          // if there is no userId in cookie header, return null
          if (start == -1)
          return userId;
          end = HTTP_Request.indexOf(";",start);
          // check for the end of this cookie
          if (end == -1)
          end = HTTP_Request.indexOf("\n",start);
          // get the value of userId in cookie header
          userId = HTTP_Request.substring(start+7,end);
    }
    catch (Exception e) {
          System.out.println("Some sorta error" +e);
    }
    return(userId);
  }

  // check whether the preference object of this user is already
  // in ActiveCache. If true, just read the preference and return it.
  // Otherwise, lookup the preference on the server by sending a request
  // to the cgi script on server, save the response (i.e. preference) as
  // an object into ActiveCache and read and return the preference
  public static String getPrefs(String userId){
    String prefs = "ERROR";
    try {
      String url_output="";
      StringBuffer strbuf = new StringBuffer(0);
      String prepend = "prefs"+userId;
      // prepend is the name of the object for perference in ActiveCache
      byte buf[] = new byte[8192];
      int cnt;

      // If we already have this users preferences cached in ActiveCache,
      // just read in the object
      if (is_in_cache(prepend)) {
        int fd = open(prepend, 0);
        while ((cnt = read(fd, buf, 8192)) >0) {
                for (int i=0; i<cnt; i++)
                        strbuf.append((char)buf[i]);
        }
        close(fd);
      }
      // else get them from the server, read it, and cache it
      else {
        String url="GET /cgi-bin/get_prefs.cgi?userId="+userId+" HTTP/1.0\n\n";
        // send request to the cgi script and look up preference
        int fd = send_request_to_server(url);
        // save the result in ActiveCache
        int cachefd = create(prepend,00700);
        while ((cnt = read(fd, buf, 8192)) >0) {
                write(cachefd, buf, cnt);
                for (int i=0; i<cnt; i++)
                        strbuf.append((char)buf[i]);
        }
        close(fd);
        close(cachefd);
      }

      // get the preference string from the response (or cached object)
      // it starts with "Preference:" and ends with "\n"
      url_output = strbuf.toString();
      int start = url_output.indexOf("Preferences: ");
      int end = url_output.indexOf("\n",start);
      if ((start != -1) && (end != -1)) {
        prefs = url_output.substring(start+13,end);
        return prefs;
      }
    }
    catch (Exception e) {
      System.out.println("getPrefs Exception " +e); }
    return prefs;
  }
 
  // create the new document based on the user preference
  public static void createPage(int output, String prefs){
    try {
      byte buf1[] = new byte[1];
      // write the response header into the new document
      String text1 = "HTTP/1.1 200 OK\n\n";
      for (int i = 0; i < text1.length(); i++) {
        buf1[0] = (byte)text1.charAt(i);
        write (output, buf1, 1);
      }

      // parse the preference string, the format is like:
      // .left=aa:ab:ac&.right=ba:bb:bc:bd&.headlines=ca:cb:cc:cd
      // aa, ab, etc each corresponds to one topic that user prefers
      // and each has one html document that contains links related
      // to the topic
      String left, right, news, element;
      int marker1, marker2;

      // get the left preferences
      marker1 = prefs.indexOf("&");
      left = prefs.substring(0, marker1);
      // get the right preferences
      marker2 = prefs.indexOf("&", marker1 + 1);
      right = prefs.substring(marker1 + 1, marker2);
      // get the headlines preferences
      news = prefs.substring(marker2 + 1, prefs.length());

      // write the logo to the new document first
      writeFile(output, "logo");

      // write each left preference into the new document now
      marker1 = left.indexOf("=");
      marker2 = left.indexOf(":");
      while (marker2 != -1) {
        element = left.substring(marker1+1,marker2);
        // write this preference to new document
        writeFile(output, element);
        marker1 = marker2;
        // get the next left preference here
        marker2 = left.indexOf(":",marker1+1);
      }

      byte buf[] = new byte[1];
      // put the yahoo banner here in the document
      String text = "<hr size=0><img src=\"http://www.yahoo.com/images/my/"+
        "banner/myyahoo.gif\" width=204 height=1></td><td align=left valign="+
        "top><table border=0 cellpadding=2 cellspacing=0 width=\"100%\">\n";
      for (int i = 0; i < text.length(); i++) {
        buf[0] = (byte)text.charAt(i);
        write (output, buf, 1);
      }

      // write the right preferences and headline preferences
      // into the new document
      marker1 = right.indexOf("=");
      marker2 = right.indexOf(":");
      while (marker2 != -1) {
        element = right.substring(marker1+1,marker2);
        // if element is channel start the news
        if (element.equals("channel")){
          int mark1 = news.indexOf("=");
          int mark2 = news.indexOf(":");
          while (mark2 != -1) {
            element = news.substring(mark1+1,mark2);
            writeFile(output, element);
            mark1 = mark2;
            mark2 = news.indexOf(":",mark1+1);
          }
          // we need to end the table for headlines
          text = "</table>\n";
          for (int i = 0; i < text.length(); i++) {
            buf[0] = (byte)text.charAt(i);
            write (output, buf, 1);
          }
        }
        else {
          writeFile(output, element);
        }
        marker1 = marker2;
        marker2 = right.indexOf(":",marker1+1);
      }
      // write a footer to the end of new document
      writeFile(output, "footer");
    }
    catch(Exception e){
      System.out.println("createPage error: "+e);
    }
  }

  // Write out a preference into the new document
  // filename is the name of the preference
  public static void writeFile(int output, String filename) {
    try{
      byte buf[] = new byte[8192];
        int cnt;

      // if the html document corresponding to this preference
      // is in ActiveCache, just write it to new document
      if (is_in_cache(filename+".html")){
        int fd = open(filename+".html", 0);
        while ( (cnt = read(fd, buf, 8192) ) >0) {
          write(output, buf, cnt);
        }
        close(fd);
      }
      // otherwise, we get it from the server, create it in ActiveCache
      // as an object, and write it to the new document
      else {
        String file = "/~kbeach/wisweb/serverdata/"+filename+".html";
        int cachefd = create(filename+".html",00700);
        String url = "GET "+file+" HTTP/1.0\n\n";
        int urlfd = send_request_to_server(url);

        // This while loop cuts through all the headers.
        boolean char1 = false, char2 = false;
        int val=1;
        while (!char2 && (val != -1)) {
          val = read(urlfd, buf, 1);    // needs to be fixed;
          if (char1 && ((char)buf[0] == '\r'))
            char2 = true;
          else if ((char)buf[0] == '\n') {
            char1 = true;
          }
          else {
            char1 = false;
          }
        }
        // now that we are past the headers lets get the content
        while ((cnt = read(urlfd, buf, 8192)) > 0)  {
          // writing both to ActiveCache object and new document
          write(output, buf, cnt);
          write(cachefd, buf, cnt);
        }
        close(urlfd);
        close(cachefd);
      }
    }
    catch(Exception e) {
      System.out.println("Error read in createPage: "+e);
    }
  }

  // sendPrefsPage - this user has no Cookie: userId, send the
  // prefs page so they can set one up.
  public static void sendPrefsPage(){
    System.out.println("************** sendingPrefsPage **************");
  }
}