/*
 * Copyright 2010 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.google.gwt.sample.expenses.client;

import com.google.gwt.cell.client.AbstractCell;
import com.google.gwt.core.client.GWT;
import com.google.gwt.requestfactory.shared.Receiver;
import com.google.gwt.safehtml.client.SafeHtmlTemplates;
import com.google.gwt.safehtml.shared.SafeHtml;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.sample.expenses.client.request.ExpenseProxy;
import com.google.gwt.sample.expenses.client.request.ExpensesRequestFactory;
import com.google.gwt.sample.expenses.client.request.ReportProxy;
import com.google.gwt.user.cellview.client.CellList;
import com.google.gwt.user.cellview.client.HasKeyboardSelectionPolicy.KeyboardSelectionPolicy;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.view.client.AsyncDataProvider;
import com.google.gwt.view.client.HasData;
import com.google.gwt.view.client.NoSelectionModel;
import com.google.gwt.view.client.SelectionChangeEvent;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * TODO: doc.
 */
public class MobileExpenseList extends Composite implements MobilePage {

  /**
   * TODO: doc.
   */
  public interface Listener {
    void onCreateExpense(ReportProxy report);

    void onEditReport(ReportProxy report);

    void onExpenseSelected(ExpenseProxy expense);
  }

  interface Template extends SafeHtmlTemplates {
    @Template("<div class=\"item\">{0}{1} ({2})</div>")
    SafeHtml div(SafeHtml approvalIcon, String description, String amount);
  }

  /**
   * The cell used to render {@link ExpenseProxy}s.
   */
  private class ExpenseCell extends AbstractCell<ExpenseProxy> {

    private final SafeHtml approvedHtml;
    private final String approvedText = Expenses.Approval.APPROVED.getText();
    private final SafeHtml blankHtml;
    private final SafeHtml deniedHtml;
    private final String deniedText = Expenses.Approval.DENIED.getText();

    public ExpenseCell() {
      if (template == null) {
        template = GWT.create(Template.class);
      }
      approvedHtml = Expenses.Approval.APPROVED.getIconHtml();
      blankHtml = Expenses.Approval.BLANK.getIconHtml();
      deniedHtml = Expenses.Approval.DENIED.getIconHtml();
    }

    @Override
    public void render(ExpenseProxy value, Object viewData, SafeHtmlBuilder sb) {
      String approval = value.getApproval();
      SafeHtml approvalIcon;
      if (approvedText.equals(approval)) {
        approvalIcon = approvedHtml;
      } else if (deniedText.equals(approval)) {
        approvalIcon = deniedHtml;
      } else {
        approvalIcon = blankHtml;
      }
      sb.append(template.div(approvalIcon, value.getDescription(),
          ExpensesMobile.formatCurrency(value.getAmount())));
    }
  }

  private static Template template;

  /**
   * The auto refresh interval in milliseconds.
   */
  private static final int REFRESH_INTERVAL = 5000;

  private final ExpensesRequestFactory requestFactory;
  private final CellList<ExpenseProxy> expenseList;
  private final AsyncDataProvider<ExpenseProxy> expenseDataProvider;
  private final NoSelectionModel<ExpenseProxy> expenseSelection;

  /**
   * The set of Expense keys that we already know are denied. When a new key is
   * added, we compare it to the list of known keys to determine if it is new.
   */
  private Set<Object> knownDeniedKeys = null;

  /**
   * The receiver for the last request.
   */
  private Receiver<List<ExpenseProxy>> lastReceiver;

  private ReportProxy report;
  private final Listener listener;

  /**
   * The {@link Timer} used to periodically refresh the table.
   */
  private final Timer refreshTimer = new Timer() {
    @Override
    public void run() {
      requestExpenses();
    }
  };

  public MobileExpenseList(
      final Listener listener, final ExpensesRequestFactory requestFactory) {
    this.listener = listener;
    this.requestFactory = requestFactory;
    expenseDataProvider = new AsyncDataProvider<ExpenseProxy>(Expenses.EXPENSE_RECORD_KEY_PROVIDER) {
      @Override
      protected void onRangeChanged(HasData<ExpenseProxy> view) {
        requestExpenses();
      }
    };

    expenseList = new CellList<ExpenseProxy>(new ExpenseCell());
    expenseList.setKeyboardSelectionPolicy(KeyboardSelectionPolicy.DISABLED);

    expenseSelection = new NoSelectionModel<ExpenseProxy>();
    expenseList.setSelectionModel(expenseSelection);
    expenseSelection.addSelectionChangeHandler(
        new SelectionChangeEvent.Handler() {
          public void onSelectionChange(SelectionChangeEvent event) {
            listener.onExpenseSelected(
                expenseSelection.getLastSelectedObject());
          }
        });

    expenseDataProvider.addDataDisplay(expenseList);
    initWidget(expenseList);
  }

  @Override
  public Widget asWidget() {
    return this;
  }

  public String getPageTitle() {
    return report != null ? report.getPurpose() : "";
  }

  public boolean needsAddButton() {
    return true;
  }

  public String needsCustomButton() {
    return "Edit";
  }

  public boolean needsRefreshButton() {
    return true;
  }

  public void onAdd() {
    listener.onCreateExpense(report);
  }

  public void onCustom() {
    listener.onEditReport(report);
  }

  public void onRefresh(boolean clear) {
    if (clear) {
      expenseDataProvider.updateRowCount(0, true);
    }
    requestExpenses();
  }

  public void show(ReportProxy report) {
    this.report = report;
    knownDeniedKeys = null;

    onRefresh(true);
  }

  private String[] getExpenseColumns() {
    return new String[]{"description", "amount"};
  }

  /**
   * Request the expenses.
   */
  private void requestExpenses() {
    refreshTimer.cancel();
    if (requestFactory == null || report == null) {
      return;
    }
    lastReceiver = new Receiver<List<ExpenseProxy>>() {
      @Override
      public void onSuccess(List<ExpenseProxy> newValues) {
        if (this == lastReceiver) {
          int size = newValues.size();
          expenseDataProvider.updateRowCount(size, true);
          expenseDataProvider.updateRowData(0, newValues);

          // Add the new keys to the known keys.
          boolean isInitialData = knownDeniedKeys == null;
          if (knownDeniedKeys == null) {
            knownDeniedKeys = new HashSet<Object>();
          }
          for (ExpenseProxy value : newValues) {
            Object key = expenseDataProvider.getKey(value);
            String approval = value.getApproval();
            if (Expenses.Approval.DENIED.getText().equals(approval)) {
              if (!isInitialData && !knownDeniedKeys.contains(key)) {
                (new PhaseAnimation.CellListPhaseAnimation<ExpenseProxy>(
                    expenseList, value, expenseDataProvider)).run();
              }
              knownDeniedKeys.add(key);
            } else {
              knownDeniedKeys.remove(key);
            }
          }

          refreshTimer.schedule(REFRESH_INTERVAL);
        }
      }
    };
    requestFactory.expenseRequest().findExpensesByReport(
        report.getId()).with(getExpenseColumns()).fire(
        lastReceiver);
  }
}
