/*
 * Copyright(C) 2010 avanza Co.,Ltd. All rights reserved.
 * http://www.avnz.co.jp/
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

package com.aimluck.eip.enquete;

import java.util.ArrayList;
import java.util.List;

import org.apache.cayenne.access.DataContext;
import org.apache.cayenne.exp.Expression;
import org.apache.cayenne.exp.ExpressionFactory;
import org.apache.cayenne.query.Ordering;
import org.apache.cayenne.query.SelectQuery;
import org.apache.jetspeed.services.logging.JetspeedLogFactoryService;
import org.apache.jetspeed.services.logging.JetspeedLogger;
import org.apache.turbine.util.RunData;
import org.apache.velocity.context.Context;

import com.aimluck.commons.field.ALStringField;
import com.aimluck.eip.cayenne.om.portlet.AvzTEnquete;
import com.aimluck.eip.cayenne.om.portlet.AvzTEnqueteChoiceItem;
import com.aimluck.eip.cayenne.om.portlet.AvzTEnqueteItem;
import com.aimluck.eip.common.ALAbstractFormData;
import com.aimluck.eip.common.ALDBErrorException;
import com.aimluck.eip.common.ALPageNotFoundException;
import com.aimluck.eip.enquete.util.EnqueteUtils;
import com.aimluck.eip.modules.actions.common.ALAction;
import com.aimluck.eip.orm.DatabaseOrmService;
import com.aimluck.eip.services.eventlog.ALEventlogConstants;
import com.aimluck.eip.services.eventlog.ALEventlogFactoryService;
import com.aimluck.eip.util.ALEipUtils;

/**
 * Enqueteのフォームデータを管理するクラスです。 <BR>
 * 
 */
public class EnqueteAnswerFormData extends ALAbstractFormData {

  /** logger */
  private static final JetspeedLogger logger =
    JetspeedLogFactoryService.getLogger(EnqueteFormData.class.getName());

  private DataContext dataContext;

  /** アンケート名 */
  private ALStringField name;

  /** コメント */
  private ALStringField comment;

  /** アンケート作成者 */
  private ALStringField creater_name;

  /** アンケート項目・選択肢取得リスト */
  private List itemresults;

  /**
   * init
   * 
   * @param action
   * @param rundata
   * @param context
   * @see com.aimluck.eip.common.ALAbstractFormData#init(com.aimluck.eip.modules.actions.common.ALAction,
   *      org.apache.turbine.util.RunData, org.apache.velocity.context.Context)
   */
  @Override
  public void init(ALAction action, RunData rundata, Context context)
      throws ALPageNotFoundException, ALDBErrorException {

    super.init(action, rundata, context);

    dataContext = DatabaseOrmService.getInstance().getDataContext();

    /**
     * 下記のコメントアウトのようにアクセスコントロールを追加する場合は
     * com.aimluck.eip.services.accessctl.ALAccessControlConstantsに
     * アクセスコントロール用の定数を追加してください。 (例) public static final String
     * POERTLET_FEATURE_ENQUETE_ENQUETE_OTHER = "enquete_enquete_other";
     */

    // aclPortletFeature =
    // ALAccessControlConstants.POERTLET_FEATURE_ENQUETE_ENQUETE_SELF;
  }

  /**
   * 各フィールドを初期化します。 <BR>
   * 
   * @see com.aimluck.eip.common.ALData#initField()
   */
  public void initField() {

    // アンケート名
    name = new ALStringField();
    name.setFieldName("アンケート名");

    // メモ
    comment = new ALStringField();
    comment.setFieldName("コメント");

    // アンケート作成者
    creater_name = new ALStringField();
    creater_name.setFieldName("作成者");
  }

  /**
   * アンケートの各フィールドに対する制約条件を設定します。 <BR>
   * 
   * @see com.aimluck.eip.common.ALAbstractFormData#setValidator()
   */
  @Override
  protected void setValidator() {

  }

  /**
   * 
   * @param rundata
   * @param context
   * @param msgList
   * @return
   * @see com.aimluck.eip.common.ALAbstractFormData#setFormData(org.apache.turbine.util.RunData,
   *      org.apache.velocity.context.Context, java.util.ArrayList)
   */
  @Override
  protected boolean setFormData(RunData rundata, Context context,
      List<String> msgList) throws ALPageNotFoundException, ALDBErrorException {
    boolean res = super.setFormData(rundata, context, msgList);

    return res;
  }

  /**
   * アンケートのフォームに入力されたデータの妥当性検証を行います。 <BR>
   * 
   * @param msgList
   * @return TRUE 成功 FALSE 失敗
   * @see com.aimluck.eip.common.ALAbstractFormData#validate(java.util.ArrayList)
   */
  @Override
  protected boolean validate(List<String> msgList) {
    return (msgList.size() == 0);
  }

  /**
   * アンケートをデータベースから読み出します。 <BR>
   * 
   * @param rundata
   * @param context
   * @param msgList
   * @return TRUE 成功 FALSE 失敗
   * @see com.aimluck.eip.common.ALAbstractFormData#loadFormData(org.apache.turbine.util.RunData,
   *      org.apache.velocity.context.Context)
   */
  @Override
  protected boolean loadFormData(RunData rundata, Context context,
      List<String> msgList) {

    try {
      // // オブジェクトモデルを取得
      AvzTEnquete enquete = EnqueteUtils.getAvzTEnquete(rundata, context);
      if (enquete == null) {
        return false;
      }

      // アンケート名
      name.setValue(enquete.getName());
      // コメント
      comment.setValue(enquete.getComment());
      // アンケート作成者
      creater_name.setValue(ALEipUtils.getUserFullName(enquete.getCreaterId()));

      // アンケート項目入力フォーム内のデータの取得
      SelectQuery itemquery = new SelectQuery(AvzTEnqueteItem.class);
      Expression itemexp =
        ExpressionFactory
          .matchDbExp(AvzTEnqueteItem.AVZ_TENQUETE_PROPERTY
            + "."
            + AvzTEnquete.ENQUETE_ID_PK_COLUMN, enquete
            .getEnqueteId()
            .toString());
      itemquery.setQualifier(itemexp);
      itemquery.setDistinct(true);
      itemquery.addOrdering(AvzTEnqueteItem.ITEM_NUMBER_PROPERTY, Ordering.ASC);

      List itemlist = dataContext.performQuery(itemquery);
      int loginuserid = Integer.valueOf(ALEipUtils.getUserId(rundata));

      itemresults = new ArrayList();

      for (int i = 0; i < itemlist.size(); i++) {
        AvzTEnqueteItem item = (AvzTEnqueteItem) itemlist.get(i);
        EnqueteItemRecordData d = new EnqueteItemRecordData();
        ALStringField record = new ALStringField();

        d.setItemId(item.getItemId());
        int item_id = item.getItemId();
        d.setItemNumber(item.getItemNumber());
        record.setValue(item.getItemTitle());
        d.setItemName(record);
        d.setStatus(item.getStatus());
        d.setChoiceItemName(EnqueteUtils.getAnswerChoiceItem(
          rundata,
          context,
          item_id,
          loginuserid));

        itemresults.add(d);

      }

    } catch (Exception ex) {
      dataContext.rollbackChanges();
      logger.error("Exception", ex);
      return false;
    }
    return true;
  }

  /**
   * Enqueteをデータベースに格納します。 <BR>
   * 
   * @param rundata
   * @param context
   * @param msgList
   * @return TRUE 成功 FALSE 失敗
   * @see com.aimluck.eip.common.ALAbstractFormData#insertFormData(org.apache.turbine.util.RunData,
   *      org.apache.velocity.context.Context, java.util.ArrayList)
   */
  @Override
  protected boolean insertFormData(RunData rundata, Context context,
      List<String> msgList) {

    return true;
  }

  /**
   * データベースに格納されているEnqueteを更新します。 <BR>
   * 
   * @param rundata
   * @param context
   * @param msgList
   * @return TRUE 成功 FALSE 失敗
   * @see com.aimluck.eip.common.ALAbstractFormData#updateFormData(org.apache.turbine.util.RunData,
   *      org.apache.velocity.context.Context, java.util.ArrayList)
   */
  @Override
  protected boolean updateFormData(RunData rundata, Context context,
      List<String> msgList) {
    try {
      // オブジェクトモデルを取得
      AvzTEnquete enquete = EnqueteUtils.getAvzTEnquete(rundata, context);
      if (enquete == null) {
        return false;
      }

      // ログインユーザーのIDを取得
      int loginuserid = Integer.valueOf(ALEipUtils.getUserId(rundata));

      // 該当アンケートの選択状態を初期化
      SelectQuery resetquery = new SelectQuery(AvzTEnqueteChoiceItem.class);
      // アンケートIDを取得
      Expression rexp =
        ExpressionFactory.matchDbExp(
          AvzTEnqueteChoiceItem.AVZ_TENQUETE_PROPERTY
            + "."
            + AvzTEnquete.ENQUETE_ID_PK_COLUMN,
          enquete.getEnqueteId());
      // ログインユーザーIDを取得
      Expression rexp2 =
        ExpressionFactory.matchExp(
          AvzTEnqueteChoiceItem.ANSWER_ID_PROPERTY,
          loginuserid);

      resetquery.setQualifier(rexp.andExp(rexp2));
      List resetChoice = dataContext.performQuery(resetquery);

      for (int i = 0; i < resetChoice.size(); i++) {

        // 選択肢IDの取得
        AvzTEnqueteChoiceItem citem =
          (AvzTEnqueteChoiceItem) resetChoice.get(i);
        citem.setStatus(EnqueteUtils.STATUS_NO_SELECT);
        citem.setResponseStatus(EnqueteUtils.RESPONSE_STATUS_BEFORE);

      }

      // 該当アンケートの項目数を取得
      List itemSum = enquete.getAvzTEnqueteItem();

      // 項目数分ループさせる
      for (int j = 0; j < itemSum.size(); j++) {

        String item_select_flag = null;
        int num = j + 1;

        SelectQuery itemquery = new SelectQuery(AvzTEnqueteItem.class);
        // アンケートIDを取得
        Expression exp =
          ExpressionFactory.matchDbExp(AvzTEnqueteItem.AVZ_TENQUETE_PROPERTY
            + "."
            + AvzTEnquete.ENQUETE_ID_PK_COLUMN, enquete.getEnqueteId());
        // 項目番号を取得
        Expression exp2 =
          ExpressionFactory.matchExp(AvzTEnqueteItem.ITEM_NUMBER_PROPERTY, num);

        itemquery.setQualifier(exp.andExp(exp2));
        List itemN = dataContext.performQuery(itemquery);
        // 項目IDの取得
        AvzTEnqueteItem item = (AvzTEnqueteItem) itemN.get(0);
        String itemId = item.getItemId().toString();
        // 状態（単一/複数/フリーテキスト）の取得
        String status = item.getStatus().toString();

        if (EnqueteUtils.STATUS_FREE_TEXT.equals(status)) {
          String select =
            rundata.getParameters().getString("choice_item_title[" + num + "]");
          // フリーテキスト用メソッドには、item_select_flagの代わりにselectを渡す
          freeTextCheck(rundata, enquete, itemId, select, loginuserid);
        } else {
          // フリーテキスト以外の場合
          // 選択された選択肢を取得
          String[] select = new String[100];
          select =
            rundata
              .getParameters()
              .getStrings("choice_item_title[" + num + "]");
          if (select == null) {
            // 回答した箇所だけ保存する
            continue;
          }
          for (int k = 0; k < select.length; k++) {

            item_select_flag = select[k];

            selectCheck(rundata, enquete, itemId, item_select_flag, loginuserid);
          }
        }

      }

      dataContext.commitChanges();

      // イベントログに保存
      ALEventlogFactoryService.getInstance().getEventlogHandler().log(
        enquete.getEnqueteId(),
        ALEventlogConstants.PORTLET_TYPE_NONE,
        name.getValue());

    } catch (Exception ex) {
      dataContext.rollbackChanges();
      logger.error("Exception", ex);
      return false;
    }
    return true;
  }

  private boolean selectCheck(RunData rundata, AvzTEnquete enquete,
      String itemId, String item_select_flag, int loginuserid) {

    SelectQuery query = new SelectQuery(AvzTEnqueteChoiceItem.class);
    // アンケートIDを取得
    Expression exp =
      ExpressionFactory.matchDbExp(AvzTEnqueteChoiceItem.AVZ_TENQUETE_PROPERTY
        + "."
        + AvzTEnquete.ENQUETE_ID_PK_COLUMN, enquete.getEnqueteId());
    // ログインユーザーIDを取得
    Expression exp2 =
      ExpressionFactory.matchExp(
        AvzTEnqueteChoiceItem.ANSWER_ID_PROPERTY,
        loginuserid);
    // 項目ID取得
    Expression exp3 =
      ExpressionFactory.matchDbExp(
        AvzTEnqueteChoiceItem.AVZ_TENQUETE_ITEM_PROPERTY
          + "."
          + AvzTEnqueteItem.ITEM_ID_PK_COLUMN,
        itemId);

    query.setQualifier(exp.andExp(exp2).andExp(exp3));
    query.addOrdering(
      AvzTEnqueteChoiceItem.CHOICE_ITEM_NUMBER_PROPERTY,
      Ordering.ASC);
    List allChoice = dataContext.performQuery(query);

    for (int i = 0; i < allChoice.size(); i++) {

      // 選択肢番号を設定
      int choicenum = i + 1;

      AvzTEnqueteChoiceItem choiceitem =
        (AvzTEnqueteChoiceItem) allChoice.get(i);

      if (item_select_flag == null) {
      } else if (("" + choicenum + "").equals(item_select_flag)) {

        // 選択した選択肢を「選択」状態にする
        choiceitem.setStatus(EnqueteUtils.STATUS_SELECT);

        // 回答したアンケートを回答済にする
        query.setQualifier(exp.andExp(exp2));
        List choice = dataContext.performQuery(query);

        for (int j = 0; j < choice.size(); j++) {

          choiceitem = (AvzTEnqueteChoiceItem) choice.get(j);
          choiceitem.setResponseStatus(EnqueteUtils.RESPONSE_STATUS_AFTER);

        }

      }

    }

    return true;

  }

  private boolean freeTextCheck(RunData rundata, AvzTEnquete enquete,
      String itemId, String free_text, int loginuserid) {

    SelectQuery query = new SelectQuery(AvzTEnqueteChoiceItem.class);
    // アンケートIDを取得
    Expression exp =
      ExpressionFactory.matchDbExp(AvzTEnqueteChoiceItem.AVZ_TENQUETE_PROPERTY
        + "."
        + AvzTEnquete.ENQUETE_ID_PK_COLUMN, enquete.getEnqueteId());
    // ログインユーザーIDを取得
    Expression exp2 =
      ExpressionFactory.matchExp(
        AvzTEnqueteChoiceItem.ANSWER_ID_PROPERTY,
        loginuserid);
    // 項目ID取得
    Expression exp3 =
      ExpressionFactory.matchDbExp(
        AvzTEnqueteChoiceItem.AVZ_TENQUETE_ITEM_PROPERTY
          + "."
          + AvzTEnqueteItem.ITEM_ID_PK_COLUMN,
        itemId);

    query.setQualifier(exp.andExp(exp2).andExp(exp3));
    query.addOrdering(
      AvzTEnqueteChoiceItem.CHOICE_ITEM_NUMBER_PROPERTY,
      Ordering.ASC);
    List allChoice = dataContext.performQuery(query);

    for (int i = 0; i < allChoice.size(); i++) {

      // 選択肢番号を設定
      int choicenum = i + 1;

      AvzTEnqueteChoiceItem choiceitem =
        (AvzTEnqueteChoiceItem) allChoice.get(i);

      // 回答内容をセットする
      ALStringField freeText = new ALStringField();
      freeText.setValue(free_text);
      choiceitem.setChoiceItemTitle(freeText.getValue());

      // 回答したフリーテキストを「選択」状態にする
      choiceitem.setStatus(EnqueteUtils.STATUS_SELECT);

      // 回答したアンケートを回答済にする
      query.setQualifier(exp.andExp(exp2));
      List choice = dataContext.performQuery(query);

      for (int j = 0; j < choice.size(); j++) {

        choiceitem = (AvzTEnqueteChoiceItem) choice.get(j);
        choiceitem.setResponseStatus(EnqueteUtils.RESPONSE_STATUS_AFTER);

      }

    }

    return true;

  }

  /**
   * Enqueteをデータベースから削除します。 <BR>
   * 
   * @param rundata
   * @param context
   * @param msgList
   * @return TRUE 成功 FALSE 失敗
   * @see com.aimluck.eip.common.ALAbstractFormData#deleteFormData(org.apache.turbine.util.RunData,
   *      org.apache.velocity.context.Context)
   */
  @Override
  protected boolean deleteFormData(RunData rundata, Context context,
      List<String> msgList) {

    return true;
  }

  public static JetspeedLogger getLogger() {
    return logger;
  }

  public DataContext getDataContext() {
    return dataContext;
  }

  /**
   * アンケート名を取得します。 <BR>
   * 
   * @return
   */
  public ALStringField getName() {
    return name;
  }

  /**
   * @return
   */
  public String getComment() {
    return ALEipUtils.getMessageList(comment.getValue());
  }

  /**
   * アンケート作成者を取得します。 <BR>
   * 
   * @return
   */
  public ALStringField getCreaterName() {
    return creater_name;
  }

  /**
   * アンケート項目・選択肢取得リストを取得します。 <BR>
   * 
   * @return
   */

  public List getItemResults() {
    return itemresults;
  }

}
