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

import java.util.ArrayList;
import java.util.List;
import java.util.jar.Attributes;

import org.apache.cayenne.DataRow;
import org.apache.cayenne.exp.Expression;
import org.apache.cayenne.exp.ExpressionFactory;
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.AvzTLunchOrder;
import com.aimluck.eip.cayenne.om.portlet.AvzTLunchOrderItem;
import com.aimluck.eip.cayenne.om.portlet.AvzTLunchUserOrder;
import com.aimluck.eip.common.ALAbstractSelectData;
import com.aimluck.eip.common.ALDBErrorException;
import com.aimluck.eip.common.ALEipConstants;
import com.aimluck.eip.common.ALPageNotFoundException;
import com.aimluck.eip.lunchorder.util.LunchOrderUtils;
import com.aimluck.eip.modules.actions.common.ALAction;
import com.aimluck.eip.orm.Database;
import com.aimluck.eip.orm.query.ResultList;
import com.aimluck.eip.orm.query.SQLTemplate;
import com.aimluck.eip.orm.query.SelectQuery;
import com.aimluck.eip.util.ALEipUtils;

/**
 * 集計データを管理するクラスです。 <BR>
 * 
 */
public class LunchOrderTotalSelectData extends
    ALAbstractSelectData<AvzTLunchOrderItem, Object> {

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

  /** オーダーしたユーザーリスト */
  private List<LunchOrderForUserTotalResultData> orderUserList;

  /** 選択された弁当屋ID */
  private int storeMapId;

  /** 選択された弁当屋名 */
  private ALStringField storeName;

  /** 注文金額（総合計） */
  private int totalPrice;

  /** 注文数（総合計） */
  private int totalAmount;

  /** ユーザー毎集計用商品名 */
  private String sourceOrderItemName;

  /** ユーザー毎集計用注文数 */
  private int orderSumForUser;

  @Override
  public void init(ALAction action, RunData rundata, Context context)
      throws ALPageNotFoundException, ALDBErrorException {
    super.init(action, rundata, context);
  }

  @Override
  public void initField() {
    storeName = new ALStringField();
  }

  /**
   * 集計用データを取得します。（ユーザー毎）
   * 
   * @author uehara-yuki
   */
  public void loadOrderUserList(RunData rundata, Context context) {
    try {
      // 弁当注文しているユーザーがいるかどうか検索
      orderUserList = new ArrayList<LunchOrderForUserTotalResultData>();

      storeMapId = getOrderMapId();

      // SQLの作成
      StringBuffer idStatement = new StringBuffer();
      idStatement.append("SELECT DISTINCT ");
      idStatement.append("  A.USER_ID ");
      idStatement.append("FROM AVZ_T_LUNCH_USER_ORDER as A ");
      idStatement.append("LEFT JOIN AVZ_T_LUNCH_ORDER_ITEM as B ");
      idStatement.append("  on A.ITEM_ID = B.ITEM_ID ");
      idStatement.append("LEFT JOIN AVZ_T_LUNCH_ORDER as C ");
      idStatement.append("  on B.ORDER_MAP_ID = C.ORDER_MAP_ID ");
      idStatement.append("WHERE C.ORDER_MAP_ID  = ").append(storeMapId);

      String idQuery = idStatement.toString();

      SQLTemplate<AvzTLunchUserOrder> orderForUser =
        Database.sql(AvzTLunchUserOrder.class, idQuery);
      List<DataRow> orderForUsers = orderForUser.fetchListAsDataRow();

      int userSize = orderForUsers.size();
      DataRow dataRow;
      if (userSize > 0) {// 弁当注文しているユーザーがいる場合
        for (int i = 0; i < userSize; i++) {
          sourceOrderItemName = "";
          orderSumForUser = 0;
          dataRow = orderForUsers.get(i);
          int userId =
            (((Integer) ALEipUtils.getObjFromDataRow(
              dataRow,
              AvzTLunchUserOrder.USER_ID_COLUMN)).intValue());

          // SQLの作成
          StringBuffer itemStatement = new StringBuffer();
          itemStatement.append("SELECT DISTINCT ");
          itemStatement.append("  A.ITEM_ID ");
          itemStatement.append("FROM AVZ_T_LUNCH_USER_ORDER as A ");
          itemStatement.append("LEFT JOIN AVZ_T_LUNCH_ORDER_ITEM as B ");
          itemStatement.append("  on A.ITEM_ID = B.ITEM_ID ");
          itemStatement.append("LEFT JOIN AVZ_T_LUNCH_ORDER as C ");
          itemStatement.append("  on B.ORDER_MAP_ID = C.ORDER_MAP_ID ");
          itemStatement.append("WHERE C.ORDER_MAP_ID  = ").append(storeMapId);
          itemStatement.append(" AND A.USER_ID  = ").append(userId);

          String itemQuery = itemStatement.toString();

          SQLTemplate<AvzTLunchUserOrder> orderItem =
            Database.sql(AvzTLunchUserOrder.class, itemQuery);
          List<DataRow> orderItems = orderItem.fetchListAsDataRow();

          int orderItemSize = orderItems.size();
          DataRow dataRowForItem;
          for (int k = 0; k < orderItemSize; k++) {// 注文した商品ごとの注文数を検索
            dataRowForItem = orderItems.get(k);
            int itemId =
              (((Integer) ALEipUtils.getObjFromDataRow(
                dataRowForItem,
                AvzTLunchUserOrder.ITEM_ID_COLUMN)).intValue());

            // SQLの作成
            StringBuffer amountStatement = new StringBuffer();
            amountStatement.append("SELECT ORDER_AMOUNT ");

            amountStatement.append("FROM AVZ_T_LUNCH_USER_ORDER  ");
            amountStatement.append("WHERE ITEM_ID  = ").append(itemId);
            amountStatement.append(" AND USER_ID  = ").append(userId);

            String sumQuery = amountStatement.toString();

            SQLTemplate<AvzTLunchUserOrder> orderSum =
              Database.sql(AvzTLunchUserOrder.class, sumQuery);
            List<DataRow> orderSums = orderSum.fetchListAsDataRow();
            int orderSumSize = orderSums.size();
            DataRow dataRowForOrderSums;
            int combineOrderSum = 0;
            for (int m = 0; m < orderSumSize; m++) {// 同一商品の注文数は足していく処理
              dataRowForOrderSums = orderSums.get(m);
              combineOrderSum =
                combineOrderSum
                  + (((Integer) ALEipUtils.getObjFromDataRow(
                    dataRowForOrderSums,
                    AvzTLunchUserOrder.ORDER_AMOUNT_COLUMN)).intValue());
              if (m == orderSumSize - 1) {// 同一商品が無い場合
                if (sourceOrderItemName == "") {// 先頭の場合は「弁当名：注文数」（例）「のり弁当：４」）の形にする処理
                  sourceOrderItemName =
                    LunchOrderUtils.getItemName(itemId) + "：" + combineOrderSum;
                  orderSumForUser = orderSumForUser + combineOrderSum;
                } else {// 先頭以外だったら先頭の後に「、」をつけて結合させる処理
                  sourceOrderItemName =
                    sourceOrderItemName
                      + "、"
                      + LunchOrderUtils.getItemName(itemId)
                      + "："
                      + combineOrderSum;
                  orderSumForUser = orderSumForUser + combineOrderSum;
                }
              }

            }
          }
          // ユーザごとの条件わけの処理が終了したらセットしていく
          LunchOrderForUserTotalResultData rd =
            new LunchOrderForUserTotalResultData();// インスタンス生成
          rd.initField();
          rd.setOrderUserName(ALEipUtils.getUserFullName(userId));
          rd.setOrderItemName(sourceOrderItemName);
          rd.setOrderAmount(orderSumForUser);
          rd.setOrderPrice(LunchOrderUtils.getTotalPrice(userId, storeMapId));
          orderUserList.add(rd);// velocityで取り出すためのリスト（orderUserList）に結果を載せる }
        }

      } else {// 弁当注文しているユーザーがいない場合
        // 処理なし
      }

    } catch (Exception ex) {
      logger.error("Exception", ex);
    }

  }

  /**
   * 集計用データを取得します。(弁当毎) <BR>
   * 
   * @param rundata
   * @param context
   * @return
   * @see com.aimluck.eip.common.ALAbstractListData#selectData(org.apache.turbine.util.RunData,
   *      org.apache.velocity.context.Context)
   */
  @Override
  public ResultList<AvzTLunchOrderItem> selectList(RunData rundata,
      Context context) {
    try {

      storeMapId =
        Integer.parseInt(ALEipUtils.getTemp(
          rundata,
          context,
          ALEipConstants.ENTITY_ID));// 選択された弁当屋IDを親クラスのメソッドにて取得

      SelectQuery<AvzTLunchOrderItem> query = getSelectQuery(rundata, context);

      buildSelectQueryForListView(query);
      query.orderAscending("itemTitle");
      ResultList<AvzTLunchOrderItem> list = query.getResultList();// getSelectQueryのquery実行

      storeName.setValue(LunchOrderUtils.getStoreName(storeMapId));// 変数に取得した弁当屋名をセット
      totalAmount = LunchOrderUtils.getTotalSum(storeMapId);// 合計注文数を変数に入れる
      totalPrice = LunchOrderUtils.getTotalPrice(storeMapId);// 合計金額を変数に入れる

      return list;

    } catch (Exception ex) {
      logger.error("Exception", ex);
      return null;
    }

  }

  /**
   * 検索条件を設定した SelectQuery を返します。 <BR>
   * 
   * @param rundata
   * @param context
   * @return
   */
  private SelectQuery<AvzTLunchOrderItem> getSelectQuery(RunData rundata,
      Context context) {

    // 選択された弁当屋の商品データを検索するための条件
    Expression exp03 =
      ExpressionFactory.matchDbExp(
        AvzTLunchOrderItem.TO_AVZ_TLUNCH_ORDER_PROPERTY
          + "."
          + AvzTLunchOrder.ORDER_MAP_ID_PK_COLUMN,
        storeMapId);

    SelectQuery<AvzTLunchOrderItem> query =
      Database.query(AvzTLunchOrderItem.class, exp03);

    return query;
  }

  /**
   * ResultData に値を格納して返します。（集計データ） <BR>
   * 
   * @param obj
   * @return
   * @see com.aimluck.eip.common.ALAbstractSelectData#getListData(java.lang.Object)
   */
  @Override
  protected Object getResultData(AvzTLunchOrderItem obj) {
    try {

      AvzTLunchOrderItem record = obj;

      LunchOrderTotalResultData rd = new LunchOrderTotalResultData();// インスタンス生成

      rd.initField();// オブジェクトのフィールドを初期化

      /** 注文数(弁当毎) */
      int orderAmount = 0;

      /** 注文金額(弁当毎) */
      int orderPrice = 0;

      /** 弁当単価 */
      int itemPrice = 0;

      rd.setOrderItemName(record.getItemTitle()); // 弁当名セット

      /** 弁当毎のIｄ */
      int itemId = record.getItemId();

      Expression exp11 =
        ExpressionFactory.matchDbExp(// 選択された弁当屋に対する注文商品を検索するための条件
          AvzTLunchUserOrder.TO_AVZ_TLUNCH_ORDER_ITEM_PROPERTY
            + "."
            + AvzTLunchOrderItem.ITEM_ID_PK_COLUMN,
          itemId);

      SelectQuery<AvzTLunchUserOrder> orderItemquery =
        Database.query(AvzTLunchUserOrder.class, exp11);

      ResultList<AvzTLunchUserOrder> orderItemList =
        orderItemquery.getResultList();// query実行

      for (int i = 0; i < orderItemList.size(); i++) {
        AvzTLunchUserOrder atzLunchUserOrder = orderItemList.get(i);

        orderAmount = orderAmount + atzLunchUserOrder.getOrderAmount();// 注文数を変数に入れていく

      }

      rd.setOrderAmount(orderAmount);// 注文数セット

      itemPrice = record.getPrice();// 弁当の単価を変数に入れる

      orderPrice = orderAmount * itemPrice;// 弁当ごとの小計金額変数に入れる

      rd.setOrderPrice(orderPrice);// 弁当ごとの小計金額セット

      return rd;

    } catch (Exception ex) {
      logger.error("Exception", ex);
      return null;
    }

  }

  /**
   * 弁当屋IDを取得します
   * 
   * @author uehara-yuki
   */
  public int getOrderMapId() {
    return storeMapId;
  }

  /**
   * 弁当屋名を取得します
   * 
   * @autor yuki-uehara
   */
  public ALStringField getStoreName() {
    return storeName;
  }

  /**
   * 合計金額を取得します
   * 
   * @autor yuki-uehara
   */
  public int getTotalPrice() {
    return totalPrice;
  }

  /**
   * 合計注文数を取得します
   * 
   * @autor yuki-uehara
   */
  public int getTotalAmount() {
    return totalAmount;
  }

  /**
   * 
   * @return
   */
  public List<LunchOrderForUserTotalResultData> getOrderUserList() {
    return orderUserList;
  }

  /**
   * @return
   * @see com.aimluck.eip.common.ALAbstractSelectData#getColumnMap()
   */
  @Override
  protected Attributes getColumnMap() {
    return null;
  }

  /**
   * 詳細データを取得します。 <BR>
   * 
   * @param rundata
   * @param context
   * @return
   * @see com.aimluck.eip.common.ALAbstractSelectData#selectDetail(org.apache.turbine.util.RunData,
   *      org.apache.velocity.context.Context)
   */
  @Override
  public Object selectDetail(RunData rundata, Context context)
      throws ALPageNotFoundException {
    return null;
  }

  /**
   * ResultData に値を格納して返します。（詳細データ） <BR>
   * 
   * @param obj
   * @return
   * @see com.aimluck.eip.common.ALAbstractSelectData#getResultDataDetail(java.lang.Object)
   */
  @Override
  protected Object getResultDataDetail(Object obj) {
    return null;
  }

}
