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

package jp.sourceforge.livez.ezweb;

import javax.servlet.http.HttpServletRequest;

import jp.sourceforge.livez.IllegalRequestException;

import org.apache.commons.lang.StringUtils;
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 org.apache.commons.lang.math.NumberUtils;

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

	/**
	 * HTTPリクエスト情報からクラスを構築します。
	 * 
	 * @param request HTTPリクエスト情報
	 * @throws IllegalRequestException
	 */
	public EZwebRequestImpl(final HttpServletRequest request) throws IllegalRequestException {
		this.userAgent = new EZwebUserAgentImpl(request);

		String[] strings;

		this.EZServerName = request.getHeader("x-up-uplink");
		this.titlebar = "1".equals(request.getHeader("x-up-devcap-titlebar"));
		this.colorScreen = "1".equals(request.getHeader("x-up-devcap-iscolor"));
		this.maxDataSize = NumberUtils.toInt(request.getHeader("x-up-devcap-max-pdu"));
		this.softkeys = NumberUtils.toInt(request.getHeader("x-up-devcap-numsoftkeys"));

		strings = getTwoNumberProperty(request, "x-up-devcap-screenchars");
		if (strings != null) {
			this.characterMaxLength	= NumberUtils.toInt(strings[0]);
			this.characterMaxRow	= NumberUtils.toInt(strings[1]);
		}

		this.color = getColor(request.getHeader("x-up-devcap-screendepth"));

		strings = getTwoNumberProperty(request, "x-up-devcap-screenpixels");
		if (strings != null) {
			this.browserWidth	= NumberUtils.toInt(strings[0]);
			this.browserHeight = NumberUtils.toInt(strings[1]);
		}

		this.softkeyLabelLength = NumberUtils.toInt(request.getHeader("x-up-devcap-softkeysize"));

		try {
			this.subscriberId = new SubscriberIdImpl(request);
		} catch (NullPointerException e) {
			this.subscriberId = null;
		}

		this.sid = request.getHeader("x-up-devcap-zone");

		try {
			this.dataFormat = new EZwebMultiMediaImpl(request);
		} catch (IllegalArgumentException e) {
			throw new IllegalRequestException(e.getMessage(), e);
		}

		this.cc = "1".equals(request.getHeader("x-up-devcap-cc"));
		this.qvga = "1".equals(request.getHeader("x-up-devcap-qvga"));
		this.nonAttachment = "1".equals(request.getHeader("x-up-devcap-nonattachment"));
	}

	private static int getColor(final String screendepth) {
		int depth = 0;

		// 後ろに「, RGB332」がついてくる端末があるので split する 
		String[] strings = StringUtils.defaultString(screendepth).split(",");
		String str = strings[0];

		// 一部の端末では色深度ではなく色数を返してしまうので変換
		if (str.equals("256"))
			str = "8";
		if (NumberUtils.isNumber(str))
			depth = NumberUtils.toInt(str);

		return (2 ^ depth);
	}

	private static String[] getTwoNumberProperty(final HttpServletRequest request, final String propertyName) {
		String[] ret = null;

		String str = request.getHeader(propertyName);
		if (StringUtils.isNotEmpty(str)) {
			String[] works = str.split(",");
			if (works.length == 2) {
				if (NumberUtils.isNumber(works[0]) && NumberUtils.isNumber(works[1])) {
					ret = works;
				}
			}
		}

		return ret;
	}

	private EZwebUserAgent userAgent = null;

	/*
	 * @see jp.sourceforge.livez.MobilePhoneRequest#getUserAgent()
	 */
	public final EZwebUserAgent getUserAgent() {
		return userAgent;
	}

	private String EZServerName = null;

	/*
	 * @see jp.sourceforge.livez.ezweb.EZwebRequest#getEZServerName()
	 */
	public String getEZServerName() {
		return EZServerName;
	}

	private boolean titlebar = false;

	/*
	 * @see jp.sourceforge.livez.ezweb.EZwebRequest#isTitlebar()
	 */
	public final boolean isTitlebar() {
		return titlebar;
	}

	private boolean colorScreen = false;

	/*
	 * @see jp.sourceforge.livez.ezweb.EZwebRequest#isColorScreen()
	 */
	public final boolean isColorScreen() {
		return colorScreen;
	}

	private int maxDataSize = 0;

	/*
	 * @see jp.sourceforge.livez.ezweb.EZwebRequest#getMaxDataSize()
	 */
	public final int getMaxDataSize() {
		return maxDataSize;
	}

	private int softkeys = 0;

	/*
	 * @see jp.sourceforge.livez.ezweb.EZwebRequest#getSoftkeys()
	 */
	public final int getSoftkeys() {
		return softkeys;
	}

	private int characterMaxLength = 0;

	/*
	 * @see jp.sourceforge.livez.ezweb.EZwebRequest#getCharacterColumn()
	 */
	public final int getCharacterColumn() {
		return characterMaxLength;
	}

	private int characterMaxRow = 0;

	/*
	 * @see jp.sourceforge.livez.ezweb.EZwebRequest#getCharacterRow()
	 */
	public final int getCharacterRow() {
		return characterMaxRow;
	}

	private int color = 0;

	/*
	 * @see jp.sourceforge.livez.ezweb.EZwebRequest#getColor()
	 */
	public final int getColor() {
		return color;
	}

	private int browserWidth = 0;

	/*
	 * @see jp.sourceforge.livez.ezweb.EZwebRequest#getBrowserWidth()
	 */
	public final int getBrowserWidth() {
		return browserWidth;
	}

	private int browserHeight = 0;

	/*
	 * @see jp.sourceforge.livez.ezweb.EZwebRequest#getBrowserHeight()
	 */
	public final int getBrowserHeight() {
		return browserHeight;
	}

	private int softkeyLabelLength = 0;

	/*
	 * @see jp.sourceforge.livez.ezweb.EZwebRequest#getSoftkeyLabelLength()
	 */
	public final int getSoftkeyLabelLength() {
		return softkeyLabelLength;
	}

	private SubscriberId subscriberId = null;

	/*
	 * @see jp.sourceforge.livez.ezweb.EZwebRequest#getSubscriberID()
	 */
	public final SubscriberId getSubscriberID() {
		return subscriberId;
	}

	private String sid = null;

	/*
	 * @see jp.sourceforge.livez.ezweb.EZwebRequest#getSid()
	 */
	public String getSid() {
		return sid;
	}

	/**
	 * 各種 EZweb サービスへの対応状況を保持します。
	 */
	private EZwebMultiMedia dataFormat = null;

	/*
	 * @see jp.sourceforge.livez.ezweb.EZwebRequest#getDataFormat()
	 */
	public EZwebMultiMedia getDataFormat() {
		return dataFormat;
	}

	private boolean cc = false;

	/*
	 * @see jp.sourceforge.livez.ezweb.EZwebRequest#isCc()
	 */
	public boolean isCc() {
		return cc;
	}

	private boolean qvga = false;

	/*
	 * @see jp.sourceforge.livez.ezweb.EZwebRequest#isQvga()
	 */
	public boolean isQvga() {
		return qvga;
	}

	private boolean nonAttachment = false;

	/*
	 * @see jp.sourceforge.livez.ezweb.EZwebRequest#isNonAttachment()
	 */
	public boolean isNonAttachment() {
		return nonAttachment;
	}

	@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);
	}

}
