package jp.co.nri.rid.search;

/* misc */
import java.util.Vector;
import java.awt.Color;

/* Rid */
import jp.co.nri.Rid;
import jp.co.nri.rid.xml.elementBooster;


/**
 * DetailInfo の解析
 */
class SPTableModelDetailInfo extends SPTableModel{
    /** SCCS ID */
    private static final String SCCSID = "@(#)SPTableModelDetailInfo.java";

    /** RCS ID */
    private static final String RCSID =
	"$Id: SPTableModelDetailInfo.java,v 1.12 2003-07-18 17:48:29+09 nsmr Exp $";

    /** セルに背景色を設定する際の色 */
    // static final String CELL_BACKGROUND = "DDF0FF";
    static final String CELL_BACKGROUND = "F4F7F9";

    /** セルに背景色を設定する際の色 */
    static final Color BACKGROUND_COLOR = hexToColor(CELL_BACKGROUND);


    /**
     * コンストラクタ:
     */
    SPTableModelDetailInfo(int target) {
        this.target = target;

        /* 検索した個数 */
        count = 0;

        /* 検索結果保持 Vector を初期化 */
        resultVector = new Vector();

        /* 1行分の表示文字列を保持する配列 */
        String[] rowStrings;

        /* 1行分の背景色を保持する配列 */
        Color[] rowColors;

        /* 1セル分の背景色を保持 */
        Color cellBackground;

        /* 行の背景色を設定するか否か保持するフラグ */
        boolean backgroundFlag = true;

        /* DOCUMENT_SITE の PaegUnit をすべて取得 */
        elementBooster[] pageUnits =
            getElementsFromDocument("PageUnit", Rid.DOCUMENT_SITE);

        /* PageUnit が存在しなければ */
        if (pageUnits.length <= 0) {
            return;
        }

        int[] columnIDs = SPColumnNames.get(target);

        for (int i = 0; i < pageUnits.length; i++) {
            if (pageUnits[i].isNull()) {
                continue;
            }

            /* DetailInfo を持たない PageUnit は無視 */
            elementBooster detailInfo = pageUnits[i].child("DetailInfo");
            if (detailInfo == null) {
                continue;
            }

            /* 子供を持たない DetailInfo  は無視 */
            elementBooster[] detailChildren = detailInfo.children();
            if (detailChildren == null) {
                continue;
            }

            rowColors = new Color[columnIDs.length];
            rowStrings = new String[columnIDs.length];

            /* ファイル名を表示 */
            if (pageUnits[i].attribute("File") != null) {
                rowStrings =
                    addStringToRowStrings(rowStrings, target,
                                          SPColumnNames.FILE,
                                          pageUnits[i].attribute("File"));
            } else {
                rowStrings = addStringToRowStrings(rowStrings, target,
                                                   SPColumnNames.FILE, "");
            }

            for (int j = 0; j < detailChildren.length; j++) {
                /* 現在の検索対象で、扱うべきエレメント以外は無視 */
                if (!isTargetElement(target, detailChildren[j])) {
                    continue;
                }

                /* 現在注目しているファイル内で 2 つ目以降の detailChildren 
                   の場合、1 つ目の detailChildren ですでにファイル名は表示して
                   あるので、ここでは "File" のカラムは何も表示しない */
                if (rowStrings == null) {
                    rowColors = new Color[columnIDs.length];
                    rowStrings = new String[columnIDs.length];

                    /* 明示的に File カラムを "" にしないと、elementBooster
                       の File アトリビュートが表示されてしまう */
                    rowStrings = addStringToRowStrings(rowStrings, target,
                                                       SPColumnNames.FILE, "");
                }

                if (target == META) {
                    rowStrings =
                        metaInfoAnalyze(rowStrings, detailChildren[j]);
                    resultVector.add(new SPElementAndStrings(pageUnits[i],
                                                             rowStrings));
                    rowStrings = null;
                    count++;
                    continue;
                }

                if (target == STYLESHEET) {
                    rowStrings =
                        stylesheetAnalyze(rowStrings, detailChildren[j]);
                    resultVector.add(new SPElementAndStrings(pageUnits[i],
                                                             rowStrings));
                    rowStrings = null;
                    count++;
                    continue;
                }

                if (target == SCRIPT) {
                    rowStrings =
                        scriptAnalyze(rowStrings, detailChildren[j]);
                    resultVector.add(new SPElementAndStrings(pageUnits[i],
                                                             rowStrings));
                    rowStrings = null;
                    count++;
                    continue;
                }

                if (target != FORM) {
                    continue;
                }
                /* 以下の処理は form に対するもの */

                if (backgroundFlag) {
                    cellBackground = BACKGROUND_COLOR;
                    backgroundFlag = false;
                } else {
                    cellBackground = null;
                    backgroundFlag = true;
                }

                /* DetailInfo の直接の子供として input 系がある場合 */
                if (detailChildren[j].tagname().equals("button") ||
                    detailChildren[j].tagname().equals("input") ||
                    detailChildren[j].tagname().equals("textarea")) {
                    rowStrings = addStringToRowStrings(rowStrings, target,
                                                       SPColumnNames.FORM_NAME,
                                                       "(n/a)");
                    rowStrings = addElementToRowStrings(rowStrings,
                                                        detailChildren[j]);
                    rowColors = setColorToRow(rowColors, cellBackground);
                    resultVector.add(new SPElementAndStrings(pageUnits[i],
                                                             rowStrings,
                                                             rowColors));
                    rowStrings = null;
                    rowColors = null;
                    count++;

                    continue;
                }

                /* DetailInfo の直接の子供として select がある場合 */
                if (detailChildren[j].tagname().equals("select")) {
                    rowStrings = addStringToRowStrings(rowStrings, target,
                                                       SPColumnNames.FORM_NAME,
                                                       "(n/a)");
                    rowStrings = addElementToRowStrings(rowStrings,
                                                        detailChildren[j]);
                    rowColors = setColorToRow(rowColors, cellBackground);
                    resultVector.add(new SPElementAndStrings(pageUnits[i],
                                                             rowStrings,
                                                             rowColors));
                    rowStrings = null;
                    rowColors = null;
                    count++;
                    /* select に囲まれた option を列挙 */
                    elementBooster[] options = detailChildren[j].children();
                    for (int m = 0; m < options.length; m++) {
                        if (options[m].tagname().equals("option")) {
                            rowStrings = addElementToRowStrings(rowStrings,
                                                                options[m]);
                            rowColors = setColorToRow(rowColors,
                                                      cellBackground);
                            resultVector.add(new
                                SPElementAndStrings(pageUnits[i], rowStrings,
                                                    rowColors));
                            rowStrings = null;
                            rowColors = null;
                            count++;
                        }
                    }
                    continue;
                } /* if (detailChildren[j].tagname().equals("select")) */

                /* DetailInfo の直接の子供が form の場合 */
                /* 各アトリビュートの表示 */
                if (detailChildren[j].attribute("name") != null) {
                    rowStrings =
                        addStringToRowStrings(rowStrings, target,
                                              SPColumnNames.FORM_NAME,
                                              detailChildren[j].attribute("name"));
                }
                if (detailChildren[j].attribute("action") != null) {
                    rowStrings =
                        addStringToRowStrings(rowStrings, target,
                                              SPColumnNames.ACTION, 
                                              detailChildren[j].attribute("action"));
                }
                if (detailChildren[j].attribute("method") != null) {
                    rowStrings =
                        addStringToRowStrings(rowStrings, target,
                                              SPColumnNames.METHOD,
                                              detailChildren[j].attribute("method"));
                }

                /* form の子供達を表示 */
                elementBooster[] inputs = detailChildren[j].children();

                /* input 系を持たない form の場合 */
                if (inputs == null) {
                    rowStrings =
                        addStringToRowStrings(rowStrings, target,
                                              SPColumnNames.INPUT_NAME,
                                              "(n/a)");
                    rowColors = setColorToRow(rowColors, cellBackground);
                    resultVector.add(new SPElementAndStrings(pageUnits[i],
                                                             rowStrings,
                                                             rowColors));
                    rowStrings = null;
                    rowColors = null;
                    count++;
                    continue;
                }
                
                for (int k = 0; k < inputs.length; k++) {
                    rowStrings = addElementToRowStrings(rowStrings, inputs[k]);
                    rowColors = setColorToRow(rowColors, cellBackground);
                    resultVector.add(new SPElementAndStrings(pageUnits[i],
                                                             rowStrings,
                                                             rowColors)); 
                    rowStrings = null;
                    rowColors = null;
                    count++;

                    /* select に囲まれた option を列挙 */
                    if (inputs[k].tagname().equals("select")) {
                        elementBooster[] options = inputs[k].children();
                        for (int m = 0; m < options.length; m++) {
                            if (options[m].tagname().equals("option")) {
                                rowStrings =
                                    addElementToRowStrings(rowStrings,
                                                           options[m]);
                                rowColors = setColorToRow(rowColors,
                                                          cellBackground);
                                resultVector.add(new
                                    SPElementAndStrings(pageUnits[i],
                                                        rowStrings,
                                                        rowColors));
                                rowStrings = null;
                                rowColors = null;
                                count++;
                            }
                        }
                    }
                } /* for (int k = 0; k < inputs.length; k++)  */
            } /* for (int j = 0; j < detailChildren.length; j++) */
            
            /* DetailInfo に form / input がなかった場合、または
               DetailInfo の最後の項目が、form / input 以外だった場合は、
               rowStrings は resultVector に add せずに捨てられる */

        } /* for (int i = 0; i < pageUnits.length; i++) */
    } /* コンストラクタ */


    /**
     * DetailInfo のエレメントが、
     * 指定された検索対象時に扱うべきものか否かを返す
     *
     * @param target 検索対象の識別名
     * @param element DetailInfo のエレメント
     * @return 扱うべきエレメントの場合は true
     */
    private boolean isTargetElement(int target, elementBooster element) {
        if (target == FORM) {
            /* "form detail" モードで、
               form でも input でも textarea でも select でも button でも
               ない要素は無視 */
            if (element.tagname().equals("button"))   { return true; }
            if (element.tagname().equals("form"))     { return true; }
            if (element.tagname().equals("input"))    { return true; }
            if (element.tagname().equals("select"))   { return true; }
            if (element.tagname().equals("textarea")) { return true; }
            return false;
        }

        if (target == META) {
            /* "meta detail" モードで、meta 以外の要素は無視 */
            if (element.tagname().equals("meta")) { return true;}
            return false;
        }

        if (target == STYLESHEET) {
            if (element.tagname().equals("style")) {
                return true;
            }
            if (element.tagname().equals("link")) {
                String rel = element.attribute("rel");
                if (rel == null) {
                    return false;
                }
                if (rel.equalsIgnoreCase("stylesheet")){
                    return true;
                }
                return false;
            }
            return false;
        }

        if (target == SCRIPT) {
            if (element.tagname().equals("script")) { return true;}
            return false;
        }

        return false;
    } /* isTargetElement */


    /**
     * meta タグに含まれるデータの解析
     * @param rowStrings 解析結果を格納する配列
     * @param element 解析対象の meta エレメント
     */
    private String[] metaInfoAnalyze(String[] rowStrings,
                                      elementBooster element) {
        /* 各アトリビュートの表示 */
        if (element.attribute("name") != null) {
            rowStrings = addStringToRowStrings(rowStrings, target,
                                               SPColumnNames.META_NAME,
                                               element.attribute("name"));
        }
        if (element.attribute("http-equiv") != null) {
            rowStrings =
                addStringToRowStrings(rowStrings, target,
                                      SPColumnNames.HTTP_EQUIV,
                                      element.attribute("http-equiv"));
        }
        if (element.attribute("content") != null) {
            rowStrings =
                addStringToRowStrings(rowStrings, target,
                                      SPColumnNames.CONTENT, 
                                      element.attribute("content"));
        }
        return rowStrings;
    } /* metaInfoAnalyze */


    /**
     * link or style タグに含まれるデータの解析
     */
    private String[] stylesheetAnalyze(String[] rowStrings,
                                       elementBooster element) {
        if (element.tagname().equals("style")) {
            /* style タグの場合は、type アトリビュートを表示 */
            if (element.attribute("type") != null) {
                return addStringToRowStrings(rowStrings, target,
                                             SPColumnNames.TYPE,
                                             element.attribute("type"));
            }
            return addStringToRowStrings(rowStrings, target,
                                         SPColumnNames.TYPE, "(n/a)");
        }

        if (element.tagname().equals("link")) {
            /* link タグの場合は、href または src  アトリビュートを表示 */
            if (element.attribute("rel") != null) {
                if (element.attribute("rel").equalsIgnoreCase("stylesheet")) {
                    if (element.attribute("href") != null) {
                        return
                            addStringToRowStrings(rowStrings, target,
                                                  SPColumnNames.LINK,
                                                  element.attribute("href"));
                    }
                    if (element.attribute("src") != null) {
                        return addStringToRowStrings(rowStrings, target,
                                                     SPColumnNames.LINK,
                                                     element.attribute("src"));
                    }
                    return addStringToRowStrings(rowStrings, target,
                                                 SPColumnNames.LINK,
                                                 "(n/a)");
                }

            }
        }

        return rowStrings;
    } /* stylesheetAnalyze */


    /**
     * script タグに含まれるデータの解析
     */
    private String[] scriptAnalyze(String[] rowStrings,
                                   elementBooster element) {
        if (element.attribute("language") != null) {
            rowStrings = addStringToRowStrings(rowStrings, target,
                                               SPColumnNames.LANGUAGE,
                                               element.attribute("language"));
        } else {
            rowStrings = addStringToRowStrings(rowStrings, target,
                                               SPColumnNames.LANGUAGE,
                                               "(n/a)");
        }

        if (element.attribute("type") != null) {
            rowStrings = addStringToRowStrings(rowStrings, target,
                                               SPColumnNames.TYPE,
                                               element.attribute("type"));
        }
        if (element.attribute("charset") != null) {
            rowStrings = addStringToRowStrings(rowStrings, target,
                                               SPColumnNames.CHARSET,
                                               element.attribute("charset"));
        }
        if (element.attribute("src") != null) {
            rowStrings = addStringToRowStrings(rowStrings, target,
                                               SPColumnNames.SOURCE,
                                               element.attribute("src"));
        }

        return rowStrings;
    } /* scriptAnalyze */
    

    /**
     * form 要素を rowStrings に追加する
     * @param rowStrings 追加される rowStrings
     * @param element 追加する element
     */
    String[] addElementToRowStrings(String[] rowStrings,
                                    elementBooster element){
        String tagName = element.tagname();

        if (rowStrings == null) {
            int[] columnIDs = SPColumnNames.get(target);
            if (columnIDs == null) {
                return rowStrings;
            }
            rowStrings = new String[columnIDs.length];
            rowStrings = addStringToRowStrings(rowStrings, target,
                                               SPColumnNames.FILE, "");
        }

        /* option タグの場合は、"Input Name" 列には select の名前を表示する
           ため、ここでは何も表示しない*/
        if (!tagName.equals("option")) {
            if (element.attribute("name") != null) {
                rowStrings = addStringToRowStrings(rowStrings, target,
                                                   SPColumnNames.INPUT_NAME,
                                                   element.attribute("name"));
            }
        }

        /* input, button 等のタグの場合は、
         *  "Input Type" 列に type アトリビュートも表示
         */
        String elementType = element.attribute("type");
        if (elementType == null) {
            rowStrings = addStringToRowStrings(rowStrings, target,
                                               SPColumnNames.INPUT_TYPE,
                                               tagName);
        } else if (elementType.equals("")) {
            rowStrings = addStringToRowStrings(rowStrings, target,
                                               SPColumnNames.INPUT_TYPE,
                                               tagName);
        } else {
            rowStrings =
                addStringToRowStrings(rowStrings, target,
                                      SPColumnNames.INPUT_TYPE,
                                      tagName + " (" + elementType + ")");
        }

        if (element.attribute("value") != null) {
            rowStrings = addStringToRowStrings(rowStrings, target,
                                               SPColumnNames.VALUE,
                                               element.attribute("value"));
        }

        /* checked アトリビュートのある input (チェックボックス、
           ラジオボタン等) は、checked アトリビュートを表示 */
        if (element.attribute("checked") != null) {
            rowStrings = addStringToRowStrings(rowStrings, target,
                                               SPColumnNames.CHECKED,
                                               element.attribute("checked"));
        }

        /* 画像ボタン等の場合は src アトリビュートを表示 */
        if (element.attribute("src") != null) {
            rowStrings = addStringToRowStrings(rowStrings, target,
                                               SPColumnNames.SOURCE,
                                               element.attribute("src"));
        }

        /* option タグの場合は、selected アトリビュートを表示 */
        if (element.attribute("selected") != null) {
            rowStrings = addStringToRowStrings(rowStrings, target,
                                               SPColumnNames.CHECKED,
                                               element.attribute("selected"));
        }

        return rowStrings;
    } /* addElementToRowStrings */


    Color[] addColorToRowColors(Color[] rowColors, int columnID, Color color) {
        int columnIndex = SPColumnNames.getColumnIndex(target, columnID);
        if (columnIndex < 0 || rowColors.length <= columnIndex) {
            return rowColors;
        }
        rowColors[columnIndex] = color;
        return rowColors;
    } /* addColorToRowColors */


    Color[] setColorToRow(Color[] rowColors, Color color) {

        if (rowColors == null) {
            int[] columnIDs = SPColumnNames.get(target);
            if (columnIDs == null) {
                return rowColors;
            }
            rowColors = new Color[columnIDs.length];
        }

        rowColors = addColorToRowColors(rowColors, SPColumnNames.FORM_NAME,
                                        color);
        rowColors = addColorToRowColors(rowColors, SPColumnNames.ACTION,
                                        color);
        rowColors = addColorToRowColors(rowColors, SPColumnNames.METHOD,
                                        color);
        rowColors = addColorToRowColors(rowColors, SPColumnNames.INPUT_NAME,
                                        color);
        rowColors = addColorToRowColors(rowColors, SPColumnNames.INPUT_TYPE,
                                        color);
        rowColors = addColorToRowColors(rowColors, SPColumnNames.VALUE,
                                        color);
        rowColors = addColorToRowColors(rowColors, SPColumnNames.CHECKED,
                                        color);
        rowColors = addColorToRowColors(rowColors, SPColumnNames.SOURCE,
                                        color);
        return rowColors;
    } /* setColorToRow */


    /**
     * 16進数で表された文字列を Color に変換する
     * @param str 16 進 6 桁で表された文字列
     * @return str が表す色
     */
    static Color hexToColor(String str) {
        if (str == null) {
            return Color.WHITE;
        }

        if (str.length() != 6) {
            return Color.WHITE;
        }

        int r, g, b;
        try {
            r = Integer.parseInt(str.substring(0, 2), 16);
            g = Integer.parseInt(str.substring(2, 4), 16);
            b = Integer.parseInt(str.substring(4, 6), 16);
            return new Color(r, g, b);
        } catch (NumberFormatException e) {
            return Color.WHITE;
        }
    } /* hexToColor */
} /* class SPTableModelDetailInfo */
