/* $Id: GlanceAuth.java,v 1.10 2003/08/22 15:57:12 ryanlee Exp $
 */

import java.io.*;
import java.net.*;
import java.text.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;

import com.hp.hpl.mesa.rdf.jena.common.*;
import com.hp.hpl.mesa.rdf.jena.mem.ModelMem;
import com.hp.hpl.mesa.rdf.jena.model.*;
import com.hp.hpl.mesa.rdf.jena.vocabulary.RDF;
import com.hp.hpl.mesa.rdf.jena.vocabulary.RSS;

import vocabulary.DC;
import vocabulary.GLANCE;

import util.Base64Decoder;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;


public class GlanceAuth extends HttpServlet {
    ResourceBundle rb = ResourceBundle.getBundle("LocalStrings");
    PrintWriter out = null;
    
    Hashtable users = new Hashtable();
    String auth = null;
    
    public void init(ServletConfig config)
	throws ServletException {
	super.init(config);
    }
    
    public void doGet(HttpServletRequest request,
                      HttpServletResponse response) 
	throws IOException, ServletException  {
	
	// get the users session
	HttpSession session = request.getSession();
	// session.setMaxInactiveInterval(-1);	
	
	// get the model stored in the session
	Model glance = (Model) session.getAttribute("model");
	Model personal = (Model) session.getAttribute("personal");
	int custom = 0;
	
	// get authentication information
	auth = request.getHeader("Authorization");
	
	// if no auth, then challenge for authorization
	if (auth == null) {
	    response.sendError(response.SC_UNAUTHORIZED);
	    return;
	}

	String userpassEncoded = auth.substring(6);
	String userpassDecoded = Base64Decoder.decode(userpassEncoded);
	String user = null;
	user = getUsername(userpassDecoded);
	String authuri = rb.getString("glance.authuri");

	// if no user in URI, then redirect
	if (request.getParameter("user") == null) {
	    Enumeration params = request.getParameterNames();
	    String finaluri = authuri + "?user=" + user;
	    String pName;
	    String [] pValue;
	    while(params.hasMoreElements()) {
		pName  = (String) params.nextElement();
		pValue = request.getParameterValues(pName);
		for (int j = 0; j < pValue.length; j++) {
		    finaluri += "&" + pName + "=" + URLEncoder.encode(pValue[j]);
		}
	    }
	    response.sendRedirect(finaluri);
	    return;
	}
	
	// don't cache the output
	response.setHeader("Cache-Control", "no-cache");

	// get output
        out = response.getWriter();
	
	// set the actual thing being printed to be one or the other
	if (personal != null) {
	    custom = 1;
	} else if (glance == null) {
	    // if no model exisits, create one
	    glance = new ModelMem();
	    
	    // configure base model
	    String configuri = rb.getString("glance.configuri");
	    
	    try {
		Glance.readFeed(glance, configuri, auth);
	    } catch (Exception e) {
		System.out.println(e);
	    }
       	}

	// load member feeds
	String configmemberuri = rb.getString("glance.configmemberuri");
	
	try {
	    Glance.readFeed(glance, configmemberuri, auth);
	} catch (Exception e) {
	    System.out.println(e);
	}
	    
	// load team feeds if appropriate
	String configteamuri = rb.getString("glance.configteamuri");
	
	try {
	    Glance.readFeed(glance, configteamuri, auth);
	} catch (Exception e) {
	    System.out.println(e);
	}
	
	// save model
	session.setAttribute("model", glance);
		
	try {
	    response.setContentType("text/html");
	    
	    String abouturi = rb.getString("glance.abouturi");
	    String loginuri = rb.getString("glance.loginuri");
	    String prefuri = rb.getString("glance.prefuri");

	    String navigation = "<a href=\"" + Glance.makeUserURI(loginuri, user) + "\">Home</a> | ";
	    navigation += "<a href=\"" + abouturi + "\">About</a> | ";
	    navigation += "<a href=\"" + Glance.makeUserURI(prefuri, user) + "\">Preferences</a> ";
	    Glance.printHeader(out, navigation, custom);

	    // check for feed in question (could be via http param else
	    // init param)
	    String feed = request.getParameter("feed");
	    String since = request.getParameter("since");

	    if (custom == 1) {
		String ptop = rb.getString("glance.personalfeed");

		if (feed == null) {
		    // no parameter input, perhaps init... load inital value
		    // from config file
		    feed = ptop;
		}

		Glance.readFeed(personal, ptop, auth);

		// print personal outline
		out.println("<div id=\"content\">");
		out.println("<div id=\"toc\">");

		// print outline based on base feed
		Resource base = personal.getResource(ptop);
		Glance.printDateSearch(since, out);
		printOutline(personal, glance, base, feed, "feed", auth, out);
		out.println("</div>");

		// print feed(s) in question
		Resource item = personal.getResource(feed);
		Resource gitem = glance.getResource(feed);

		out.println("<div id=\"channel\">");
		if(glance.contains(gitem, RDF.type)) {
		    Glance.printChannel(glance, gitem, auth, since, out);
		} else {
		    printChannel(personal, glance, item, auth, since, out);
		}
	    } else {
		String top = rb.getString("glance.feed");
		
		if (feed == null) {
		    // no parameter input, perhaps init... load inital value
		    // from config file
		    feed = top;
		}
		
		Glance.readFeed(glance, top, auth);
		
		out.println("<div id=\"content\">");
		
		// print outline
		out.println("<div id=\"toc\">");
		
		// print outline based on base feed
		Resource base = glance.getResource(top);
		Glance.printDateSearch(since, out);
		Glance.printOutline(glance, base, feed, "feed", auth, out);
		out.println("</div>");
		// print feed(s) in question
		Resource item = glance.getResource(feed);
		
		out.println("<div id=\"channel\">");
		Glance.printChannel(glance, item, auth, since, out);
	    }
	    out.println("</div>");

	    out.println("</div>");
	    
	    // print footer
	    Glance.printFooter(out);
	} catch (Exception e) {
	    System.out.println(e);
	}
	/*try {
	    out.println("<!--");
	    personal.write(out);
	    //glance.write(out);
	    out.println("-->");
	} catch (Exception e) {
	    System.out.println(e);
	    }*/
	out.close();
    }
    
    public void doPost(HttpServletRequest request,
		       HttpServletResponse response)
	throws IOException, ServletException {
        doGet(request, response);
    }
    
    public static String getUsername(String up) {
	String result = null;
	result = up.substring(0, up.indexOf(':'));

	return result;
    }

    public static void printOutline(Model personal,
				    Model glance,
				    Resource item,
				    String feed,
				    String qs,
				    String auth,
				    PrintWriter out) throws RDFException {
	ResourceBundle rb = ResourceBundle.getBundle("LocalStrings");
	
	String efeeduri = null;
	String docuri = rb.getString("glance.docuri");

       	if (item == null) return;

	// display nav map title
        if (item.hasProperty(GLANCE.displayTitle)) {
	    out.println("\n<ul class=\"grouping\">");
	    if(item.hasProperty(GLANCE.access, GLANCE.TeamAccess)) {
		out.println("<li class=\"team\"><img src=\"" + docuri + "team\" alt=\"Public Feed\" />");
	    } else if (item.hasProperty(GLANCE.access, GLANCE.MemberAccess)) {
		out.println("<li class=\"member\"><img src=\"" + docuri + "group\" alt=\"Public Feed\" />");
	    } else {
		out.println("<li class=\"public\"><img src=\"" + docuri + "world\" alt=\"Public Feed\" />");
	    }

	    efeeduri = URLEncoder.encode(item.toString());

	    if (auth != null) {
		String userpassEncoded = auth.substring(6);
		String userpassDecoded = Base64Decoder.decode(userpassEncoded);
		String user = GlanceAuth.getUsername(userpassDecoded);
		out.print("<a href=\"" + Glance.makeUserURI("", user, qs, efeeduri) + "\">");
	    } else {
		out.print("<a href=\"?" + qs + "=" + efeeduri + "\">");
	    }
	    out.print(item.getProperty(GLANCE.displayTitle).getString());
	    out.print("</a>");
	}
	
	// iterator over the items in the Outline
        if (item.hasProperty(RSS.items)) {
	    Seq items = item.getProperty(RSS.items).getSeq();
	    int itemmax = Integer.parseInt(rb.getString("glance.itemmax"));
	    for (int i = 1; ((i <= items.size()) && (i <= itemmax)); i++) {
		String resourceUri = items.getResource(i).toString();
		if(glance.getResource(resourceUri).hasProperty(GLANCE.displayTitle)) {
		    Glance.printOutline(glance, glance.getResource(resourceUri), feed, qs, auth, out);
		} else {
		    printOutline(personal, glance, personal.getResource(resourceUri), feed, qs, auth, out);
		}
	    }
        }

	// get member items
        if (item.hasProperty(GLANCE.mitems)) {
	    Seq items = item.getProperty(GLANCE.mitems).getSeq();
	    int itemmax = Integer.parseInt(rb.getString("glance.itemmax"));
	    for (int i = 1; ((i <= items.size()) && (i <= itemmax)); i++) {
		Glance.printOutline(glance, items.getResource(i), feed, qs, auth, out);
	    }
        }

	// get team items
        if (item.hasProperty(GLANCE.titems)) {
	    Seq items = item.getProperty(GLANCE.titems).getSeq();
	    int itemmax = Integer.parseInt(rb.getString("glance.itemmax"));
	    for (int i = 1; ((i <= items.size()) && (i <= itemmax)); i++) {
		Glance.printOutline(glance, items.getResource(i), feed, qs, auth, out);
	    }
        }

        if (item.hasProperty(GLANCE.displayTitle)) {
            out.println("</li>");
            out.println("</ul>");
	}
    }

    public static void printChannel(Model personal,
				    Model glance, 
				    Resource channel,
				    String auth,
				    String since,
				    PrintWriter out) throws RDFException {
	ResourceBundle rb = ResourceBundle.getBundle("LocalStrings");
	String docuri = rb.getString("glance.docuri");
        String uri = null;
        String title = null;
        
        // get the channel URL if it has one
        if (channel.hasProperty(RSS.link)) {
            uri = channel.getProperty(RSS.link).getString();
        }

	out.print("<div class=\"feed\">");

        // open the link tag if there is a uri
	out.print("<h3>");

        if (uri != null) {
            out.print("<a href=\"" + uri + "\">");
        }
            
        // output the title (or display title)
        if (channel.hasProperty(RSS.title)) {
	    title = channel.getProperty(RSS.title).getString();
	}

	if ((title != null) & (title != "")) {
	    out.print(title);
	} else if (channel.hasProperty(GLANCE.displayTitle)) {
            out.print(channel.getProperty(GLANCE.displayTitle).getString());
	}

        // close the link tag if there is a link
        if (uri != null) {
            out.print("</a>");
        }

	// provide link to raw news feed
	out.println("&nbsp;&nbsp;<a href=\"");
	out.println(channel.getURI());
	out.println("\"><img src=\"http://www.w3.org/RDF/icons/rdf_flyer.24\" alt=\"news feed\" border=\"0\" /></a>");

	// print access level if more restrictive than world
	if (channel.hasProperty(GLANCE.access, GLANCE.TeamAccess)) {
	    out.println("<img src=\"" + docuri + "team\" alt=\"Team Feed\" width=\"20\" height=\"14\" />");
	} else if (channel.hasProperty(GLANCE.access, GLANCE.MemberAccess)) {
	    out.println("<img src=\"" + docuri + "group\" alt=\"Member Feed\" width=\"20\" height=\"14\" />");
	}

	out.print("</h3>");

        // output the description
        if (channel.hasProperty(RSS.description)) {
            out.println("<b><span class=\"description\">");
            out.println(channel.getProperty(RSS.description).getString());
            out.println("</span></b><br />");
        }
        
        // output the image
        if (channel.hasProperty(RSS.image)) {
            Glance.printImage(glance, channel.getProperty(RSS.image).getResource(), out);
        }
        
	// print text input
        if (channel.hasProperty(RSS.textinput)) {
            Glance.printTextInput(glance, channel.getProperty(RSS.textinput).getResource(), out);
        }

        // now print the items
        if (channel.hasProperty(RSS.items)) {
	    Seq items = channel.getProperty(RSS.items).getSeq();
	    int itemmax = Integer.parseInt(rb.getString("glance.itemmax"));
	    for (int i = 1; ((i <= items.size()) && (i <= itemmax)); i++) {
		String resourceUri = items.getResource(i).toString();
		if(glance.getResource(resourceUri).hasProperty(GLANCE.displayTitle)) {
		    Glance.printItem(glance, glance.getResource(resourceUri), auth, since, out);
		} else {
		    Glance.printItem(personal, personal.getResource(resourceUri), auth, since, out);
		}
	    }
        }

	// member items
        if (channel.hasProperty(GLANCE.mitems)) {
	    Seq items = channel.getProperty(GLANCE.mitems).getSeq();
	    int itemmax = Integer.parseInt(rb.getString("glance.itemmax"));
	    for (int i = 1; ((i <= items.size()) && (i <= itemmax)); i++) {
		Glance.printItem(glance, items.getResource(i), auth, since, out);
	    }
        }

	// team items
        if (channel.hasProperty(GLANCE.titems)) {
	    Seq items = channel.getProperty(GLANCE.titems).getSeq();
	    int itemmax = Integer.parseInt(rb.getString("glance.itemmax"));
	    for (int i = 1; ((i <= items.size()) && (i <= itemmax)); i++) {
		Glance.printItem(glance, items.getResource(i), auth, since, out);
	    }
        }

	out.print("<p><a href=\"#toc\" class=\"contents\">[feed list]</a></p>");
	out.print("</div>");
    }
}
