/*******************************************************************************
 * NAME   : Passgen.js
 * AUTHOR : Prasad P. Khandekar
 * VERSION: 1.0.0
 * LICENSE: This software is goverened by KIS Public License 1.0 See accompanied
 *          License.txt for more details.
 *------------------------------------------------------------------------------
 * Copyright (c) 2005. Khan Information Systems. All Rights Reserved
 * The contents of this file are subject to the KIS Public License 1.0
 * (the "License"); you may not use this file except in compliance with the 
 * License. You should have received a copy of the KIS Public License along with 
 * this library; if not, please ask your software vendor to provide one.
 * 
 * YOU AGREE THAT THE PROGRAM IS PROVIDED AS-IS, WITHOUT WARRANTY OF ANY KIND
 * (EITHER EXPRESS OR IMPLIED) INCLUDING, WITHOUT LIMITATION, ANY IMPLIED 
 * WARRANTY OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND ANY 
 * WARRANTY OF NON INFRINGEMENT. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE 
 * PROGRAM, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * See the License.txt for the specific language governing rights and limitations 
 * under the License.
 *------------------------------------------------------------------------------
 * Pasword Patterns Elements:
 * L - Small Case Letter
 * U - Upper Case Letter
 * 9 - Digit
 * S - Symbol
 *
 * Other Options:
 * Min Length		- Minimum Length of password
 * Max Length		- Maximum Length of password
 * No Duplicates	- Allow same character to appear more than once
*******************************************************************************/
function PasswordGenerator(pstrPattern, pintMin, pintMax, pblnAllowDup)
{
	var LOWER_CASE = "abcdefghijklmnopqrstuvwzyz";
	var UPPER_CASE = "ABCDEFGHIJKLMNOPQRSTUVWZYZ";
	var NUMBERS    = "0123456789";
	var SYMBOLS    = "~!@#$%^&*()-_+={}[]|\:;?/,.<>";

	var intMin = 0;
	var intMax = 0;
	var blnAllowDup = pblnAllowDup;
	var strPattern = "";

	if (isNaN(pintMin))
		intMin = 8;
	else if (pintMin <= 0)
		intMin = 8;
	else
		intMin = pintMin;

	if (isNaN(pintMax))
		intMax = 15;
	else if (pintMax <= 0)
		intMax = 15;
	else
		intMax = pintMax;

	if (intMax < intMin) intMax = 2 * intMin;
	if (pstrPattern == null || pstrPattern == undefined || pstrPattern == "")
		strPattern = genPattern(intMax);
	else if (pstrPattern.length < intMax)
		strPattern = genPattern(intMax);
	else
		strPattern = pstrPattern.toUpperCase();

	checkPattern(strPattern);

	this.Pattern = function() {return strPattern;};
	this.Password = function() {
		var strRet = "";
		var iCntr  = 0;
		var chrTmp = "";

		for (iCntr = 0; iCntr < intMax; iCntr++)
		{
			chrTmp = strPattern.charAt(iCntr);
			switch (chrTmp)
			{
				case "9":
					chrTmp = getRandomChar(NUMBERS, strRet, blnAllowDup);
					strRet += chrTmp;
					break;					
				case "L":
					chrTmp = getRandomChar(LOWER_CASE, strRet, blnAllowDup);
					strRet += chrTmp;
					break;					
				case "U":
					chrTmp = getRandomChar(UPPER_CASE, strRet, blnAllowDup);
					strRet += chrTmp;
					break;					
				case "S":
					chrTmp = getRandomChar(SYMBOLS, strRet, blnAllowDup);
					strRet += chrTmp;
					break;					
				default:
					throw "Unsupported pattern character [" + chtTmp + "] at " + iCntr;
			}
		}
		return strRet;
	}

	function checkPattern(pstrPattern, pblnAllowDup)
	{
		var totLower = 0;
		var totUpper = 0;
		var totSym   = 0;
		var totNum   = 0;
		var arrTmp = null;

		arrTmp = pstrPattern.match("L", "g");
		if (arrTmp) totLower = arrTmp.length;
		arrTmp = pstrPattern.match("U", "g");
		if (arrTmp) totUpper = arrTmp.length;
		arrTmp = pstrPattern.match("S", "g");
		if (arrTmp) totSym = arrTmp.length;
		arrTmp = pstrPattern.match("9", "g");
		if (arrTmp) totNum = arrTmp.length;
	
		if (totLower > LOWER_CASE.length && !pblnAllowDup)
			throw "Lower case pattern exceeds avaliable charset length!";
		if (totUpper > UPPER_CASE.length && !pblnAllowDup)
			throw "Upper case pattern exceeds avaliable charset length!";
		if (totSym > SYMBOLS.length && !pblnAllowDup)
			throw "Symbol pattern exceeds avaliable charset length!";
		if (totNum > NUMBERS.length && !pblnAllowDup)
			throw "Numeric pattern exceeds avaliable charset length!";
	}
}

function genPattern(pintLen)
{
	var strRet = "";
	var iCntr  = 0;
	var rndNo  = 0;

	for (iCntr = 0; iCntr < pintLen; iCntr++)
	{
		rndNo = Math.floor((4 - 1 + 1) * Math.random() + 1)
		switch (rndNo)
		{
			case 1:
				strRet += "9";
				break;
			case 2:
				strRet += "U";
				break;
			case 3:
				strRet += "S";
				break;
			case 4:
				strRet += "L";
				break;
		}
	}
	return strRet;
}

function getRandomChar(pstrSet, pstrProcessed, pblnAllowDup)
{
	var intRnd = 0;
	var chrRet = "";
	var intLimit = pstrSet.length;

	intRnd = Math.floor((intLimit - 0 + 1) * Math.random() + 1);
	if (pblnAllowDup)
		chrRet = pstrSet.charAt(intRnd);
	else
	{
		chrRet = pstrSet.charAt(intRnd);
		while (pstrProcessed.indexOf(chrRet) >= 0)
		{
			intRnd = Math.floor((intLimit - 0 + 1) * Math.random() + 1);
			chrRet = pstrSet.charAt(intRnd);
		}
	}
	return chrRet;
}

