package org.itscool.stylist.io;

import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
import org.itscool.commons.bean.BeanFactory;
import org.itscool.commons.collection.InitParamMap;

import org.itscool.commons.util.ServletTagUtil;
import org.itscool.commons.util.TagUtil;
import org.itscool.stylist.el.LayoutRegex;
import org.itscool.stylist.tag.HtmlAttribute;
import org.itscool.stylist.tag.HtmlTag;

/**
 * XHTMLに含まれるタグの属性情報を応答データに変換します
 * @author kano
 * @version 1.00A 2006/08/09 新規作成
 */
public class HtmlAttributeConverter extends HtmlConverter{
    
    /**
     * 応答用のXHTMLデータの作成を開始します
     * @param node HtmlTagインスタンス
     * @return 応答データ
     */
    public String convert(HtmlTag node){
        StringBuffer sb = new StringBuffer();
        ArrayList attrList = node.getAttributeList();
        int size = attrList.size();
        BeanFactory factory = BeanFactory.getInstance();
        InitParamMap params = (InitParamMap)factory.getInstance("InitParams");
        LayoutRegex regex = new LayoutRegex(context, req);
        String orgPkg = params.getParam("pkgName");
        
        for(int i=0; i<size; i++){
            HtmlAttribute attr = (HtmlAttribute)attrList.get(i);
            String attrName = attr.getName();
            sb.append(" ").append(attrName);
            sb.append("=");
            sb.append("\"");
            String value = attr.getValue();
            if( attr.getName().equals(HtmlAttribute.ACTION) ||
                attr.getName().equals(HtmlAttribute.HREF) ||
                attr.getName().equals(HtmlAttribute.SRC) ||
                attr.getName().equals(HtmlAttribute.BGD)){
                value = convertRealPath(value);
            }
//modify 2007/03/17 kano start
//            //EL式とテキストに分解
//            ArrayList tagList = parseEl(value);
//            //EL式の展開を行う
//            sb.append(parseText(tagList));
            //Functionを展開する
            value = regex.replaceFunction(orgPkg, value);
            //EL式を展開する
            value = regex.replaceEl(value);
            sb.append(value);
//modify 2007/03/17 kano end
            sb.append("\"");
        }
        
        if( isCheckbox(node) ){
            //checkboxタグの場合、"checked"属性の有無を判定
            String name = node.getAttribute(HtmlAttribute.W_NAME);
            String property = node.getAttribute(HtmlAttribute.W_PROPERTY);
            String value = node.getAttribute(HtmlAttribute.VALUE);
            String w_value = node.getAttribute(HtmlAttribute.W_VALUE);
//          Object object = ServletTagUtil.findProperty(context, req, name, property, null);
            Object object;
            if( w_value != null && w_value.length() > 0 ){
                object = ServletTagUtil.findValue(context, req, w_value, null);
            }else{
                object = ServletTagUtil.findProperty(context, req, name, property, null);
            }
            //Functionを展開する
            value = regex.replaceFunction(orgPkg, value);
            //EL式を展開する
            value = regex.replaceEl(value);
            if( TagUtil.isCheckedValue(object, value) ){
                sb.append(" checked=\"true\"");
            }
        }else if( isOption(node) ){
            //optionタグの場合、"selected"属性の有無を判定
            if( isParentSelect(node) ){
                //親のタグが"select"の場合、selectで指定された値とoptionタグの値を比較
                HtmlTag parent = node.getParent();
                String name = parent.getAttribute(HtmlAttribute.W_NAME);
                String property = parent.getAttribute(HtmlAttribute.W_PROPERTY);
                String value = node.getAttribute(HtmlAttribute.VALUE);
                String w_value = node.getAttribute(HtmlAttribute.W_VALUE);
//                Object object = ServletTagUtil.findProperty(context, req, name, property, null);
                Object object;
                if( w_value != null && w_value.length() > 0 ){
                    object = ServletTagUtil.findValue(context, req, w_value, null);
                }else{
                    object = ServletTagUtil.findProperty(context, req, name, property, null);
                }
                //Functionを展開する
                value = regex.replaceFunction(orgPkg, value);
                //EL式を展開する
                value = regex.replaceEl(value);
                if( TagUtil.isCheckedValue(object, value) ){
                    sb.append(" selected=\"true\"");
                }
            }else{
                //親のタグが"select"以外の場合、自身に指定された値とoptionタグの値を比較
                String name = node.getAttribute(HtmlAttribute.W_NAME);
                String property = node.getAttribute(HtmlAttribute.W_PROPERTY);
                String value = node.getAttribute(HtmlAttribute.VALUE);
                String w_value = node.getAttribute(HtmlAttribute.W_VALUE);
//                Object object = ServletTagUtil.findProperty(context, req, name, property, null);
                Object object;
                if( w_value != null && w_value.length() > 0 ){
                    object = ServletTagUtil.findValue(context, req, w_value, null);
                }else{
                    object = ServletTagUtil.findProperty(context, req, name, property, null);
                }
                //Functionを展開する
                value = regex.replaceFunction(orgPkg, value);
                //EL式を展開する
                value = regex.replaceEl(value);
                if( TagUtil.isCheckedValue(object, value) ){
                    sb.append(" selected=\"true\"");
                }
            }
        }
        return sb.toString();
    }
    
    /**
     * この属性を含むタグがチェックボックスであるか調べます
     * @param node この属性情報に対応するタグ情報
     * @return チェックボックスの場合はtrueを返します
     */
    protected boolean isCheckbox(HtmlTag node){
        if( node.getTagName().toLowerCase().equals(HtmlAttribute.INPUT) == false ){
            return false;
        }
        HtmlAttribute type = node.getHtmlAttribute(HtmlAttribute.TYPE);
        if( type == null ){
            return false;
        }
        String checkbox = type.getValue();
        if( checkbox.toLowerCase().equals(HtmlAttribute.CHECKBOX)
        || checkbox.toLowerCase().equals(HtmlAttribute.RADIO)){
            return true;
        }else{
            return false;
        }
    }
    
    /**
     * この属性を含むタグがオプションであるか調べます
     * @param node この属性情報に対応するタグ情報
     * @return オプションの場合はtrueを返します
     */
    protected boolean isOption(HtmlTag node){
        return node.getTagName().toLowerCase().equals(HtmlAttribute.OPTION);
    }
    
    /**
     * この属性を含むタグの親がセレクトタグであるか調べます
     * @param node この属性を含むタグの親タグ
     * @return セレクトタグの場合はtrueを返します
     */
    protected boolean isParentSelect(HtmlTag node){
        HtmlTag parent = node.getParent();
        return parent.getTagName().toLowerCase().equals(HtmlTag.TAG_SELECT);
    }
    
    /**
     * 相対パスをWebアプリケーションのルートからの絶対パスに変換する
     * (相対パスの指定方法=./../..のように頭に./をつけること)
     * @param pUrl URL属性
     * @return Webアプリケーションのルートからの絶対パスに変換したURLを返します
     */
    public String convertRealPath(String pUrl){
        String contextPath = req.getContextPath();
        String realPath = "";
        String url = pUrl;
        int firstIndex = url.indexOf("./");
        if( firstIndex == 0 ){
            url = url.substring(firstIndex+2);
            
            int index = url.indexOf("../");
            List pathList = getPathList();
            int listNum = pathList.size();
            String pathListStr = "/";
            if( listNum >= 3 ){
                for(int i=0; index == 0 || (i+3) < listNum; i++ ){
                    url = url.substring(index+2);
                    pathListStr += (String)pathList.get(listNum - (i+3));
                    index = url.indexOf("../");
                    if(index == 0){
                        pathListStr += "/";
                    }
                    //				if( i==0 ){
                    //					pathListStr = "/" + pathListStr;
                    //				}
                }
                realPath = contextPath + pathListStr + url;
            }else{
                realPath = pUrl;
            }
            
        }else{
//			Object obj = ServletTagUtil.findValue(context, req, url, null);
//			if( obj != null ){
//				realPath = obj.toString();
//			}else{
//				realPath = "";
//			}
            return pUrl;
        }
        return realPath;
    }
    
    public List getPathList(){
        String sPath = req.getServletPath();
        ArrayList list = new ArrayList();
        StringTokenizer st = new StringTokenizer(sPath, "/");
        while(st.hasMoreTokens()){
            String name = (String)st.nextElement();
            list.add(name);
        }
        return list;
    }
}
