/*
 * 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.modules.screens;

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

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;

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 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.ALPageNotFoundException;
import com.aimluck.eip.enquete.EnqueteChoiceItemRecordData;
import com.aimluck.eip.enquete.EnqueteItemRecordData;
import com.aimluck.eip.enquete.util.EnqueteUtils;
import com.aimluck.eip.orm.DatabaseOrmService;
import com.aimluck.eip.util.ALEipUtils;

public class EnqueteSummaryCsvExportScreen extends ALCSVScreen {
  /**
   * logger
   */
  private static final JetspeedLogger logger =
    JetspeedLogFactoryService.getLogger(EnqueteSummaryCsvExportScreen.class
      .getName());

  /**
   * HTTP コンテンツタイプ
   * 
   * @see org.apache.turbine.modules.screens.RawScreen#getContentType(org.apache.turbine.util.RunData)
   */
  @Override
  protected String getContentType(RunData rundata) {
    return "application/octet-stream";
  }

  /**
   * 出力ファイル名（接頭辞）
   */
  private static String FILE_NAME = "";

  /**
   * 拡張子名
   */
  private static final String FILE_EXTENTION = ".csv";

  /**
   * CSVデータ改行値
   */
  private static final String LINE_SEPARATOR =
    System.getProperty("line.separator");

  /**
   * CSVデータ区切り文字
   */
  private static final String COLOMN_SEPARATOR = ",";

  /** 詳細リスト */
  private ArrayList<EnqueteChoiceItemRecordData> detailList;

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

  @Override
  protected void doOutput(RunData rundata) throws Exception {
    ServletOutputStream out = null;

    try {

      Calendar today = Calendar.getInstance();
      String result = getCSVString(rundata);
      FILE_NAME =
        name
          + "-"
          + today.get(Calendar.YEAR)
          + "-"
          + (today.get(Calendar.MONTH) + 1)
          + "-"
          + today.get(Calendar.DAY_OF_MONTH)
          + FILE_EXTENTION;
      String fileName =
        new String(FILE_NAME.getBytes("Shift_JIS"), "ISO-8859-1");

      HttpServletResponse response = rundata.getResponse();
      // ファイル名の送信(attachment部分をinlineに変更すればインライン表示)
      response.setHeader("Content-disposition", "attachment; filename=\""
        + fileName
        + "\"");
      response.setHeader("Cache-Control", "no-cache");
      response.setHeader("Pragma", "No-cache");

      // ファイル内容の出力
      out = response.getOutputStream();
      out.write(result.getBytes("MS932"));
      out.flush();
    } catch (Exception e) {
      logger.error("[ERROR]", e);
    }

  }

  /**
   * CSV文字列取り出し用メソッド。<br />
   * CSV文字列を返します。
   * 
   * @param rundata
   *            RunData
   * @return
   */
  @Override
  protected String getCSVString(RunData rundata) throws ALPageNotFoundException {
    StringBuffer sb = new StringBuffer();
    try {

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

      String enqueteId = rundata.getParameters().getString("EnqueteId");// 選択されたアンケートIDを親クラスのメソッドにて取得

      int id = Integer.valueOf(enqueteId);

      Expression exp1 =
        ExpressionFactory.matchDbExp(AvzTEnquete.ENQUETE_ID_PK_COLUMN, id);
      SelectQuery query = new SelectQuery(AvzTEnquete.class, exp1);
      List enqueteList = dataContext.performQuery(query);

      AvzTEnquete enquete = (AvzTEnquete) enqueteList.get(0);

      // 記名or無記名
      String sign = enquete.getPublicMethod();
      // アンケート名
      name = enquete.getName();

      // ヘッダライン設定
      makeHeaderLine(sb, sign);

      SelectQuery queryItem = new SelectQuery(AvzTEnqueteItem.class);
      Expression exp =
        ExpressionFactory.matchDbExp(AvzTEnqueteItem.AVZ_TENQUETE_PROPERTY
          + "."
          + AvzTEnquete.ENQUETE_ID_PK_COLUMN, id);
      queryItem.setQualifier(exp);
      queryItem.setDistinct(true);
      queryItem.addOrdering(AvzTEnqueteItem.ITEM_NUMBER_PROPERTY, Ordering.ASC);

      List list = dataContext.performQuery(queryItem);
      int listSize = list.size();

      if (EnqueteUtils.PUBLIC_METHOD_SECRET.equals(sign)) {
        // 無記名アンケートの場合

        // 回答者の一人を取得
        SelectQuery answerquery = new SelectQuery(AvzTEnqueteChoiceItem.class);

        Expression answerexp =
          ExpressionFactory.matchDbExp(
            AvzTEnqueteChoiceItem.AVZ_TENQUETE_ITEM_PROPERTY
              + "."
              + AvzTEnquete.ENQUETE_ID_PK_COLUMN,
            enquete.getEnqueteId());

        answerquery.setQualifier(answerexp);
        List getAnswer = dataContext.performQuery(answerquery);

        AvzTEnqueteChoiceItem cho = (AvzTEnqueteChoiceItem) getAnswer.get(0);
        int someAnswer = cho.getAnswerId();

        for (int i = 0; i < listSize; i++) {

          AvzTEnqueteItem item = (AvzTEnqueteItem) list.get(i);
          EnqueteItemRecordData d = new EnqueteItemRecordData();
          ALStringField record = new ALStringField();

          item.getChoiceItemNum();
          int item_id = item.getItemId();
          record.setValue(item.getItemTitle());
          d.setItemName(record);
          if (EnqueteUtils.STATUS_FREE_TEXT.equals(item.getStatus())) {
            d.setChoiceItemName(EnqueteUtils.getSummaryChoiceItemFreeText(
              rundata,
              EnqueteUtils.FLAG_CSV,
              item_id,
              someAnswer,
              enquete));
          } else {
            d.setChoiceItemName(EnqueteUtils.getSummaryChoiceItem(
              rundata,
              item_id,
              someAnswer,
              enquete,
              EnqueteUtils.FLAG_CSV));
          }

          // CSV出力処理
          for (EnqueteChoiceItemRecordData choiceItem : (List<EnqueteChoiceItemRecordData>) d
            .getChoiceItemName()) {
            // アンケート項目
            sb.append("\"" + d.getItemName() + "\"" + COLOMN_SEPARATOR);
            // 回答内容
            sb.append("\""
              + choiceItem.getCsvChoiceItem()
              + "\""
              + COLOMN_SEPARATOR);
            // 回答数
            sb.append("\""
              + choiceItem.getChoiceSelected()
              + "\""
              + COLOMN_SEPARATOR);
            sb.append(LINE_SEPARATOR);
          }

        }
      } else {
        // 記名アンケートの場合

        // 選択項目数
        int cNum = 0;
        for (int i = 0; i < listSize; i++) {
          AvzTEnqueteItem item = (AvzTEnqueteItem) list.get(i);
          EnqueteItemRecordData d = new EnqueteItemRecordData();
          ALStringField record = new ALStringField();

          item.getChoiceItemNum();
          int item_id = item.getItemId();
          record.setValue(item.getItemTitle());
          d.setItemName(record);

          // 選択項目数
          cNum = item.getChoiceItemNum();

          detailList = new ArrayList<EnqueteChoiceItemRecordData>();

          if (EnqueteUtils.STATUS_FREE_TEXT.equals(item.getStatus())) {
            // （記名用）フリーテキストメソッド呼び出し
            getFreeTextCsvElement(rundata, dataContext, item);
          } else {
            // （記名用）単一、複数選択メソッド呼び出し
            for (int j = 1; j <= cNum; j++) {
              getSelectCsvElement(rundata, item, dataContext, j);
            }
          }

          // CSV
          for (EnqueteChoiceItemRecordData choiceItem : detailList) {
            // アンケート項目
            sb.append("\"" + d.getItemName() + "\"" + COLOMN_SEPARATOR);
            // 回答内容
            sb.append("\""
              + choiceItem.getCsvChoiceItem()
              + "\""
              + COLOMN_SEPARATOR);
            // 回答者
            sb.append("\"" + choiceItem.getAnswer() + "\"" + COLOMN_SEPARATOR);
            sb.append(LINE_SEPARATOR);
          }

        }

      }

    } catch (ALPageNotFoundException pageNotFound) {
      throw pageNotFound;
    }
    return sb.toString();
  }

  @Override
  protected String getFileName() {

    return null;
  }

  /**
   * CSVのヘッダ情報を生成します。
   * 
   * @param sb
   *            StringBuffer
   */
  private void makeHeaderLine(StringBuffer sb, String sign) {

    if (EnqueteUtils.PUBLIC_METHOD_SIGNED.equals(sign)) {
      sb.append("\"アンケート項目\"" + COLOMN_SEPARATOR);
      sb.append("\"回答内容\"" + COLOMN_SEPARATOR);
      sb.append("\"回答者\"");
      sb.append(LINE_SEPARATOR);
    } else {
      sb.append("\"アンケート項目\"" + COLOMN_SEPARATOR);
      sb.append("\"回答内容\"" + COLOMN_SEPARATOR);
      sb.append("\"回答数\"");
      sb.append(LINE_SEPARATOR);
    }
  }

  // フリーテキスト用取得メソッド
  private void getFreeTextCsvElement(RunData rundata, DataContext dataContext,
      AvzTEnqueteItem item) {
    SelectQuery answerquery = new SelectQuery(AvzTEnqueteChoiceItem.class);

    Expression answerExp =
      ExpressionFactory.matchDbExp(
        AvzTEnqueteChoiceItem.AVZ_TENQUETE_ITEM_PROPERTY
          + "."
          + AvzTEnqueteItem.ITEM_ID_PK_COLUMN,
        item.getItemId());
    answerExp =
      answerExp.andExp(ExpressionFactory.matchExp(
        AvzTEnqueteChoiceItem.STATUS_PROPERTY,
        EnqueteUtils.STATUS_SELECT));
    answerExp =
      answerExp.andExp(ExpressionFactory.matchExp(
        AvzTEnqueteChoiceItem.RESPONSE_STATUS_PROPERTY,
        EnqueteUtils.RESPONSE_STATUS_AFTER));

    answerquery.setQualifier(answerExp);
    List getAnswer = dataContext.performQuery(answerquery);
    int getAnswerSize = getAnswer.size();

    if (getAnswerSize != 0) {
      // 人数分繰り返し
      for (int i = 0; i < getAnswerSize; i++) {
        AvzTEnqueteChoiceItem choice = (AvzTEnqueteChoiceItem) getAnswer.get(i);
        EnqueteChoiceItemRecordData record = new EnqueteChoiceItemRecordData();
        ALStringField answer = new ALStringField();
        answer.setValue(ALEipUtils.getUserFullName(choice.getAnswerId()));
        // 回答者
        record.setAnswer(answer);

        String choiceTitle;
        if ("".equals(choice.getChoiceItemTitle())) {
          // 空で「回答する」を押した場合
          choiceTitle = "記入なし";
        } else {
          // 空でなかった場合
          choiceTitle = choice.getChoiceItemTitle();
          choiceTitle = choiceTitle.replaceAll("\"", "\"\"");
        }
        record.setCsvChoiceItem(choiceTitle);
        detailList.add(record);
      }
    } else {
      SelectQuery query = new SelectQuery(AvzTEnqueteChoiceItem.class);

      Expression Exp =
        ExpressionFactory.matchDbExp(
          AvzTEnqueteChoiceItem.AVZ_TENQUETE_ITEM_PROPERTY
            + "."
            + AvzTEnqueteItem.ITEM_ID_PK_COLUMN,
          item.getItemId());

      query.setQualifier(Exp);
      List getNoAnswer = dataContext.performQuery(query);

      AvzTEnqueteChoiceItem choice = (AvzTEnqueteChoiceItem) getNoAnswer.get(0);
      EnqueteChoiceItemRecordData record = new EnqueteChoiceItemRecordData();
      // 選択項目タイトル
      record.setCsvChoiceItem(choice.getChoiceItemTitle());
      // 選択項目番号
      record.setChoiceItemNumber(choice.getChoiceItemNumber());
      // 回答者
      ALStringField answer = new ALStringField();
      answer.setValue("");
      record.setAnswer(answer);
      detailList.add(record);
    }
  }

  // 単一・複数選択用取得メソッド
  private void getSelectCsvElement(RunData rundata, AvzTEnqueteItem item,
      DataContext dataContext, int num) {
    SelectQuery answerquery = new SelectQuery(AvzTEnqueteChoiceItem.class);

    Expression answerExp =
      ExpressionFactory.matchDbExp(
        AvzTEnqueteChoiceItem.AVZ_TENQUETE_ITEM_PROPERTY
          + "."
          + AvzTEnqueteItem.ITEM_ID_PK_COLUMN,
        item.getItemId());
    answerExp =
      answerExp.andExp(ExpressionFactory.matchExp(
        AvzTEnqueteChoiceItem.STATUS_PROPERTY,
        EnqueteUtils.STATUS_SELECT));
    answerExp =
      answerExp.andExp(ExpressionFactory.matchExp(
        AvzTEnqueteChoiceItem.RESPONSE_STATUS_PROPERTY,
        EnqueteUtils.RESPONSE_STATUS_AFTER));
    answerExp =
      answerExp.andExp(ExpressionFactory.matchExp(
        AvzTEnqueteChoiceItem.CHOICE_ITEM_NUMBER_PROPERTY,
        num));

    answerquery.setQualifier(answerExp);
    List getAnswer = dataContext.performQuery(answerquery);
    int getAnswerSize = getAnswer.size();

    if (getAnswerSize != 0) {
      for (int i = 0; i < getAnswerSize; i++) {
        AvzTEnqueteChoiceItem choice = (AvzTEnqueteChoiceItem) getAnswer.get(i);
        EnqueteChoiceItemRecordData record = new EnqueteChoiceItemRecordData();
        // 選択項目タイトル
        record.setCsvChoiceItem(choice.getChoiceItemTitle());
        // 選択項目番号
        record.setChoiceItemNumber(choice.getChoiceItemNumber());
        // 回答者
        ALStringField answer = new ALStringField();
        answer.setValue(ALEipUtils.getUserFullName(choice.getAnswerId()));
        record.setAnswer(answer);
        detailList.add(record);
      }
    } else {
      // 選択者がいない場合

      SelectQuery query = new SelectQuery(AvzTEnqueteChoiceItem.class);

      Expression Exp =
        ExpressionFactory.matchDbExp(
          AvzTEnqueteChoiceItem.AVZ_TENQUETE_ITEM_PROPERTY
            + "."
            + AvzTEnqueteItem.ITEM_ID_PK_COLUMN,
          item.getItemId());
      Exp =
        Exp.andExp(ExpressionFactory.matchExp(
          AvzTEnqueteChoiceItem.CHOICE_ITEM_NUMBER_PROPERTY,
          num));

      query.setQualifier(Exp);
      List getNoAnswer = dataContext.performQuery(query);

      AvzTEnqueteChoiceItem choice = (AvzTEnqueteChoiceItem) getNoAnswer.get(0);
      EnqueteChoiceItemRecordData record = new EnqueteChoiceItemRecordData();
      // 選択項目タイトル
      record.setCsvChoiceItem(choice.getChoiceItemTitle());
      // 選択項目番号
      record.setChoiceItemNumber(choice.getChoiceItemNumber());
      // 回答者
      ALStringField answer = new ALStringField();
      answer.setValue("");
      record.setAnswer(answer);
      detailList.add(record);
    }
  }
}
