/*
 * Copyright (C) 2005-2006 Kouji Sugisawa. All rights reserved.
 */

package jp.sourceforge.livez.imode;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;

import jp.sourceforge.livez.IllegalUserIdException;

/**
 * UID を実装したクラスです。
 * 
 * @author 杉澤 浩二
 */
final class UIDImpl implements UID {

	private static final long serialVersionUID = 1L;

	/**
	 * 指定された文字列からUIDを構築するコンストラクタです。
	 * 
	 * @param uid UID を表す文字列
	 * @throws NullPointerException uid に null を指定した場合
	 * @throws IllegalUserIdException uid が不正な場合
	 */
	public UIDImpl(final String uid) throws NullPointerException, IllegalUserIdException {
		parse(uid);
	}

	/**
	 * HTTPリクエスト情報からUIDを構築するコンストラクタです。
	 * 
	 * @param request HTTPリクエスト情報
	 * @throws NullPointerException request 又は uid が null の場合
	 * @throws IllegalUserIdException uid が不正な場合
	 */
	public UIDImpl(final HttpServletRequest request) throws NullPointerException, IllegalUserIdException {
		parse(request.getParameter(KEY));
	}

	/**
	 * 指定された UID を解析しフィールドを設定します。
	 * 
	 * @param uid UID を表す文字列
	 * @throws NullPointerException uid に null を指定した場合
	 * @throws IllegalUserIdException uid が不正な場合
	 */
	private void parse(final String uid) throws NullPointerException, IllegalUserIdException {
//		if (uid.matches("^[0-9a-zA-Z]{12}$")) {
		if (uid.matches("^(00|01){1}[0-9a-zA-Z]{10}$")) {
			this.value = uid;
			this.member = true;

			try {
				this.type = UIDType.getUIDType(uid.substring(0, 2));
			} catch (IllegalArgumentException e) {
				throw new IllegalUserIdException(e.getMessage(), e);
			}

			this.userId	= uid.substring(2);
		} else if (DEFAULT.equals(uid)) {
			this.value = uid;
		} else
			throw new IllegalUserIdException(uid);
	}

	/**
	 * UID の値を保持します。
	 */
	private String value = null;

	/*
	 * @see jp.sourceforge.livez.UserId#getValue()
	 */
	public String getValue() {
		return value;
	}

	/**
	 * UID の種類を保持します。
	 */
	private UIDType type = null;

	/*
	 * @see jp.sourceforge.livez.imode.UID#getType()
	 */
	public UIDType getType() {
		return type;
	}

	/**
	 * ユーザIDを保持します。
	 */
	private String userId = null;

	/*
	 * @see jp.sourceforge.livez.imode.UID#getUserId()
	 */
	public String getUserId() {
		return userId;
	}

	/**
	 * 会員状態を保持します。
	 */
	private boolean member = false;

	/*
	 * @see jp.sourceforge.livez.imode.UID#isMember()
	 */
	public boolean isMember() {
		return member;
	}

	/*
	 * @see jp.sourceforge.livez.imode.UID#isGuest()
	 */
	public boolean isGuest() {
		return !member;
	}

	@Override
	public int hashCode() {
		return HashCodeBuilder.reflectionHashCode(this);
	}

	@Override
	public boolean equals(final Object obj) {
		return EqualsBuilder.reflectionEquals(this, obj);
	}

	@Override
	public String toString() {
		return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE);
	}

}
