package org.owasp.webgoat.session;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.util.Properties;

/*******************************************************************************
 * 
 * 
 * This file is part of WebGoat, an Open Web Application Security Project
 * utility. For details, please see http://www.owasp.org/
 * 
 * Copyright (c) 2002 - 2007 Bruce Mayhew
 * 
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation; either version 2 of the License, or (at your option) any later
 * version.
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 * 
 * You should have received a copy of the GNU General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
 * Place - Suite 330, Boston, MA 02111-1307, USA.
 * 
 * Getting Source ==============
 * 
 * Source for this application is maintained at code.google.com, a repository
 * for free software projects.
 * 
 * For details, please see http://code.google.com/p/webgoat/
 *
 * @author     Bruce Mayhew <a href="http://code.google.com/p/webgoat">WebGoat</a>
 * @created    October 29, 2003
 */
public class LessonTracker
{

    private boolean completed = false;

    private int maxHintLevel = 0;

    private int numVisits = 0;

    private boolean viewedCookies = false;

    private boolean viewedHtml = false;

    private boolean viewedLessonPlan = false;

    private boolean viewedParameters = false;

    private boolean viewedSource = false;

    private boolean viewedSolution = false;

    Properties lessonProperties = new Properties();


    /**
     *  Gets the completed attribute of the LessonTracker object
     *
     * @return    The completed value
     */
    public boolean getCompleted()
    {
	return completed;
    }


    /**
     *  Gets the maxHintLevel attribute of the LessonTracker object
     *
     * @return    The maxHintLevel value
     */
    public int getMaxHintLevel()
    {
	return maxHintLevel;
    }


    /**
     *  Gets the numVisits attribute of the LessonTracker object
     *
     * @return    The numVisits value
     */
    public int getNumVisits()
    {
	return numVisits;
    }


    /**
     *  Gets the viewedCookies attribute of the LessonTracker object
     *
     * @return    The viewedCookies value
     */
    public boolean getViewedCookies()
    {
	return viewedCookies;
    }


    /**
     *  Gets the viewedHtml attribute of the LessonTracker object
     *
     * @return    The viewedHtml value
     */
    public boolean getViewedHtml()
    {
	return viewedHtml;
    }


    /**
     *  Gets the viewedLessonPlan attribute of the LessonTracker object
     *
     * @return    The viewedLessonPlan value
     */
    public boolean getViewedLessonPlan()
    {
	return viewedLessonPlan;
    }


    /**
     *  Gets the viewedParameters attribute of the LessonTracker object
     *
     * @return    The viewedParameters value
     */
    public boolean getViewedParameters()
    {
	return viewedParameters;
    }


    /**
     *  Gets the viewedSource attribute of the LessonTracker object
     *
     * @return    The viewedSource value
     */
    public boolean getViewedSource()
    {
	return viewedSource;
    }


    public boolean getViewedSolution()
    {
	return viewedSource;
    }

    /**
     *  Description of the Method
     */
    public void incrementNumVisits()
    {
	numVisits++;
    }


    /**
     *  Sets the properties attribute of the LessonTracker object
     *
     * @param  props  The new properties value
     */
    protected void setProperties(Properties props, Screen screen)
    {
	completed = Boolean.valueOf(
		props.getProperty(screen.getTitle() + ".completed"))
		.booleanValue();
	maxHintLevel = Integer.parseInt(props.getProperty(screen.getTitle()
		+ ".maxHintLevel"));
	numVisits = Integer.parseInt(props.getProperty(screen.getTitle()
		+ ".numVisits"));
	viewedCookies = Boolean.valueOf(
		props.getProperty(screen.getTitle() + ".viewedCookies"))
		.booleanValue();
	viewedHtml = Boolean.valueOf(
		props.getProperty(screen.getTitle() + ".viewedHtml"))
		.booleanValue();
	viewedLessonPlan = Boolean.valueOf(
		props.getProperty(screen.getTitle() + ".viewedLessonPlan"))
		.booleanValue();
	viewedParameters = Boolean.valueOf(
		props.getProperty(screen.getTitle() + ".viewedParameters"))
		.booleanValue();
	viewedSource = Boolean.valueOf(
		props.getProperty(screen.getTitle() + ".viewedSource"))
		.booleanValue();
    }


    public static String getUserDir(WebSession s)
    {
	return s.getContext().getRealPath("users") + "/";
    }


    private static String getTrackerFile(WebSession s, String user,
	    Screen screen)
    {
	return getUserDir(s) + user + "." + screen.getClass().getName()
		+ ".props";
    }


    /**
     *  Description of the Method
     *
     * @param  screen  Description of the Parameter
     * @param  s       Description of the Parameter
     * @return         Description of the Return Value
     */
    public static LessonTracker load(WebSession s, String user, Screen screen)
    {
	FileInputStream in = null;
	try
	{
	    String fileName = getTrackerFile(s, user, screen);
	    if (fileName != null)
	    {
		Properties tempProps = new Properties();
		//System.out.println("Loading lesson state from: " + fileName);
		in = new FileInputStream(fileName);
		tempProps.load(in);
		// allow the screen to use any custom properties it may have set
		LessonTracker tempLessonTracker = screen
			.createLessonTracker(tempProps);
		tempLessonTracker.setProperties(tempProps, screen);
		return tempLessonTracker;
	    }
	}
	catch (FileNotFoundException e)
	{
	    // Normal if the lesson has not been accessed yet.
	}
	catch (Exception e)
	{
	    System.out.println("Failed to load lesson state for " + screen);
	    e.printStackTrace();
	}
	finally
	{
	    try
	    {
		in.close();
	    }
	    catch (Exception e)
	    {}
	}

	return screen.createLessonTracker();
    }


    /**
     *  Sets the completed attribute of the LessonTracker object
     *
     * @param  completed  The new completed value
     */
    public void setCompleted(boolean completed)
    {
	this.completed = completed;
    }


    /**
     *  Sets the maxHintLevel attribute of the LessonTracker object
     *
     * @param  maxHintLevel  The new maxHintLevel value
     */
    public void setMaxHintLevel(int maxHintLevel)
    {
	this.maxHintLevel = Math.max(this.maxHintLevel, maxHintLevel);
    }


    /**
     *  Sets the viewedCookies attribute of the LessonTracker object
     *
     * @param  viewedCookies  The new viewedCookies value
     */
    public void setViewedCookies(boolean viewedCookies)
    {
	this.viewedCookies = viewedCookies;
    }


    /**
     *  Sets the viewedHtml attribute of the LessonTracker object
     *
     * @param  viewedHtml  The new viewedHtml value
     */
    public void setViewedHtml(boolean viewedHtml)
    {
	this.viewedHtml = viewedHtml;
    }


    /**
     *  Sets the viewedLessonPlan attribute of the LessonTracker object
     *
     * @param  viewedLessonPlan  The new viewedLessonPlan value
     */
    public void setViewedLessonPlan(boolean viewedLessonPlan)
    {
	this.viewedLessonPlan = viewedLessonPlan;
    }


    /**
     *  Sets the viewedParameters attribute of the LessonTracker object
     *
     * @param  viewedParameters  The new viewedParameters value
     */
    public void setViewedParameters(boolean viewedParameters)
    {
	this.viewedParameters = viewedParameters;
    }


    /**
     *  Sets the viewedSource attribute of the LessonTracker object
     *
     * @param  viewedSource  The new viewedSource value
     */
    public void setViewedSource(boolean viewedSource)
    {
	this.viewedSource = viewedSource;
    }

    /**
     *  Sets the viewedSource attribute of the LessonTracker object
     *
     * @param  viewedSource  The new viewedSource value
     */
    public void setViewedSolution(boolean viewedSolution)
    {
	this.viewedSolution = viewedSolution;
    }

    /**
     *  Allows the storing of properties for the logged in and a screen.
     *
     * @param  s  Description of the Parameter
     */
    public void store(WebSession s, Screen screen)
    {
	store(s, screen, s.getUserName());
    }


    /**
     *  Allows the storing of properties for a user and a screen.
     *
     * @param  s  Description of the Parameter
     */
    public void store(WebSession s, Screen screen, String user)
    {
	FileOutputStream out = null;
	String fileName = getTrackerFile(s, user, screen);
	//System.out.println( "Storing data to" + fileName );
	lessonProperties.setProperty(screen.getTitle() + ".completed", Boolean
		.toString(completed));
	lessonProperties.setProperty(screen.getTitle() + ".maxHintLevel",
		Integer.toString(maxHintLevel));
	lessonProperties.setProperty(screen.getTitle() + ".numVisits", Integer
		.toString(numVisits));
	lessonProperties.setProperty(screen.getTitle() + ".viewedCookies",
		Boolean.toString(viewedCookies));
	lessonProperties.setProperty(screen.getTitle() + ".viewedHtml", Boolean
		.toString(viewedHtml));
	lessonProperties.setProperty(screen.getTitle() + ".viewedLessonPlan",
		Boolean.toString(viewedLessonPlan));
	lessonProperties.setProperty(screen.getTitle() + ".viewedParameters",
		Boolean.toString(viewedParameters));
	lessonProperties.setProperty(screen.getTitle() + ".viewedSource",
		Boolean.toString(viewedSource));
	try
	{
	    out = new FileOutputStream(fileName);
	    lessonProperties.store(out, s.getUserName());
	}
	catch (Exception e)
	{
	    // what do we want to do,  I think nothing.
	    System.out.println("Warning User data for " + s.getUserName()
		    + " will not persist");
	}
	finally
	{
	    try
	    {
		out.close();
	    }
	    catch (Exception e)
	    {}
	}

    }


    /**
     *  Description of the Method
     *
     * @return    Description of the Return Value
     */
    public String toString()
    {
	StringBuffer buff = new StringBuffer();
	buff.append("LessonTracker:" + "\n");
	buff.append("    - completed:.......... " + completed + "\n");
	buff.append("    - maxHintLevel:....... " + maxHintLevel + "\n");
	buff.append("    - numVisits:.......... " + numVisits + "\n");
	buff.append("    - viewedCookies:...... " + viewedCookies + "\n");
	buff.append("    - viewedHtml:......... " + viewedHtml + "\n");
	buff.append("    - viewedLessonPlan:... " + viewedLessonPlan + "\n");
	buff.append("    - viewedParameters:... " + viewedParameters + "\n");
	buff.append("    - viewedSource:....... " + viewedSource + "\n" + "\n");
	return buff.toString();
    }


    /**
     * @return Returns the lessonProperties.
     */
    public Properties getLessonProperties()
    {
	return lessonProperties;
    }


    /**
     * @param lessonProperties The lessonProperties to set.
     */
    public void setLessonProperties(Properties lessonProperties)
    {
	this.lessonProperties = lessonProperties;
    }
}