/*
 * 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.activity.shared.Activity;
import com.google.gwt.activity.shared.IsActivity;
import com.google.gwt.activity.shared.SimpleActivity;
import com.google.gwt.cell.client.AbstractCell;
import com.google.gwt.cell.client.Cell;
import com.google.gwt.cell.client.DateCell;
import com.google.gwt.cell.client.TextCell;
import com.google.gwt.cell.client.ValueUpdater;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Element;
import com.google.gwt.event.dom.client.BlurEvent;
import com.google.gwt.event.dom.client.BlurHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.FocusEvent;
import com.google.gwt.event.dom.client.FocusHandler;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyUpEvent;
import com.google.gwt.event.dom.client.KeyUpHandler;
import com.google.gwt.event.shared.EventBus;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.regexp.shared.RegExp;
import com.google.gwt.requestfactory.shared.EntityProxyChange;
import com.google.gwt.requestfactory.shared.EntityProxyId;
import com.google.gwt.requestfactory.shared.Receiver;
import com.google.gwt.requestfactory.ui.client.EntityProxyKeyProvider;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.safehtml.shared.SafeHtmlUtils;
import com.google.gwt.sample.expenses.client.place.ReportListPlace;
import com.google.gwt.sample.expenses.client.style.Styles;
import com.google.gwt.sample.expenses.shared.EmployeeProxy;
import com.google.gwt.sample.expenses.shared.ExpensesRequestFactory;
import com.google.gwt.sample.expenses.shared.ReportProxy;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiFactory;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.cellview.client.CellTable;
import com.google.gwt.user.cellview.client.Column;
import com.google.gwt.user.cellview.client.HasKeyboardSelectionPolicy.KeyboardSelectionPolicy;
import com.google.gwt.user.cellview.client.SimplePager;
import com.google.gwt.user.cellview.client.SimplePager.TextLocation;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.ui.AcceptsOneWidget;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.view.client.NoSelectionModel;
import com.google.gwt.view.client.ProvidesKey;
import com.google.gwt.view.client.Range;
import com.google.gwt.view.client.RangeChangeEvent;
import com.google.gwt.view.client.SelectionChangeEvent;

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

/**
 * The list of expense reports on the right side of the app.
 */
public class ExpenseReportList extends Composite implements
    EntityProxyChange.Handler<ReportProxy>, IsActivity {

  interface Binder extends UiBinder<Widget, ExpenseReportList> {
  }

  /**
   * Custom listener for this widget.
   */
  interface Listener {

    /**
     * Called when the user selects a report.
     * 
     * @param report the selected report
     */
    void onReportSelected(ReportProxy report);
  }

  /**
   * The resources applied to the table.
   */
  interface TableResources extends CellTable.Resources {
    @Source({CellTable.Style.DEFAULT_CSS, "ExpenseListCellTable.css"})
    TableStyle cellTableStyle();
  }

  /**
   * The styles applied to the table.
   */
  interface TableStyle extends CellTable.Style {
  }

  /**
   * A text box that displays default text.
   */
  private static class DefaultTextBox extends TextBox {

    /**
     * The text color used when the box is disabled and empty.
     */
    private static final String TEXTBOX_DISABLED_COLOR = "#aaaaaa";

    private final String defaultText;

    public DefaultTextBox(final String defaultText) {
      this.defaultText = defaultText;
      resetDefaultText();

      // Add focus and blur handlers.
      addFocusHandler(new FocusHandler() {
        public void onFocus(FocusEvent event) {
          getElement().getStyle().clearColor();
          if (defaultText.equals(getText())) {
            setText("");
          }
        }
      });
      addBlurHandler(new BlurHandler() {
        public void onBlur(BlurEvent event) {
          if ("".equals(getText())) {
            resetDefaultText();
          }
        }
      });
    }

    public String getDefaultText() {
      return defaultText;
    }

    /**
     * Reset the text box to the default text.
     */
    public void resetDefaultText() {
      setText(defaultText);
      getElement().getStyle().setColor(TEXTBOX_DISABLED_COLOR);
    }
  }

  /**
   * A cell used to highlight search text.
   */
  private class HighlightCell extends AbstractCell<String> {

    private static final String replaceString = "<span style='color:red;font-weight:bold;'>$1</span>";

    @Override
    public void render(Context context, String value, SafeHtmlBuilder sb) {
      if (value != null) {
        if (searchRegExp != null) {
          // The search regex has already been html-escaped
          value = searchRegExp.replace(SafeHtmlUtils.htmlEscape(value),
              replaceString);
          sb.append(SafeHtmlUtils.fromTrustedString(value));
        } else {
          sb.appendEscaped(value);
        }
      }
    }
  }

  private final Activity activityAspect = new SimpleActivity() {
    @Override
    public void onCancel() {
      ExpenseReportList.this.onCancel();
    }

    @Override
    public void onStop() {
      ExpenseReportList.this.onStop();
    }

    @Override
    public void start(AcceptsOneWidget panel, EventBus eventBus) {
      ExpenseReportList.this.start(panel, eventBus);
    }
  };

  private static final ProvidesKey<ReportProxy> keyProvider = new EntityProxyKeyProvider<ReportProxy>();

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

  private static Binder uiBinder = GWT.create(Binder.class);

  /**
   * Utility method to get the first part of the breadcrumb based on the
   * department and employee.
   * 
   * @param department the selected department
   * @param employee the selected employee
   * @return the breadcrumb
   */
  public static String getBreadcrumb(String department, EmployeeProxy employee) {
    assert null != department;
    if (employee != null) {
      return "Reports for " + employee.getDisplayName();
    } else if (!"".equals(department)) {
      return "Reports for " + department;
    } else {
      return "All Reports";
    }
  }

  @UiField
  Element breadcrumb;
  @UiField
  SimplePager pager;
  @UiField
  Image searchButton;

  @UiField(provided = true)
  DefaultTextBox searchBox;

  /**
   * The main table. We provide this in the constructor before calling
   * {@link UiBinder#createAndBindUi(Object)} because the pager depends on it.
   */
  @UiField(provided = true)
  CellTable<ReportProxy> table;

  private final List<SortableHeader> allHeaders = new ArrayList<SortableHeader>();

  /**
   * The department being searched.
   */
  private String department;

  /**
   * The employee being searched.
   */
  private EmployeeProxy employee;

  /**
   * Indicates that the report count is stale.
   */
  private boolean isCountStale = true;

  /**
   * The field to sort by.
   */
  private String orderBy = "purpose";

  /**
   * The set of Report keys that we have seen. When a new key is added, we
   * compare it to the list of known keys to determine if it is new.
   */
  private Set<Object> knownReportKeys = null;

  /**
   * Keep track of the last receiver so that we know if a response is stale.
   */
  private Receiver<List<ReportProxy>> lastDataReceiver;

  /**
   * Keep track of the last receiver so that we know if a response is stale.
   */
  private Receiver<Long> lastDataSizeReceiver;

  private Listener listener;

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

  /**
   * The columns to request with each report.
   */
  private final String[] reportColumns = new String[] {
      "created", "purpose", "notes"};

  /**
   * The factory used to send requests.
   */
  private final ExpensesRequestFactory requestFactory;

  /**
   * The string that the user searched for.
   */
  private RegExp searchRegExp;

  /**
   * The starts with search string.
   */
  private String startsWithSearch;

  private ReportListPlace place;

  private boolean running;

  public ExpenseReportList(ExpensesRequestFactory requestFactory) {
    this.requestFactory = requestFactory;

    // Initialize the widget.
    createTable();
    table.addRangeChangeHandler(new RangeChangeEvent.Handler() {
      public void onRangeChange(RangeChangeEvent event) {
        requestReports(false);
      }
    });
    searchBox = new DefaultTextBox("search");
    initWidget(uiBinder.createAndBindUi(this));

    // Listen for key events from the text boxes.
    searchBox.addKeyUpHandler(new KeyUpHandler() {
      public void onKeyUp(KeyUpEvent event) {
        // Search on enter.
        if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER) {
          search();
          return;
        }

        // Highlight as the user types.
        String text = SafeHtmlUtils.htmlEscape(searchBox.getText());
        if (text.length() > 0) {
          searchRegExp = RegExp.compile("(" + text + ")", "ig");
        } else {
          searchRegExp = null;
        }
        table.redraw();
      }
    });
    searchButton.addClickHandler(new ClickHandler() {
      public void onClick(ClickEvent event) {
        search();
      }
    });
  }

  public Activity asActivity() {
    return activityAspect;
  }

  public void onProxyChange(EntityProxyChange<ReportProxy> event) {
    EntityProxyId<ReportProxy> changedId = event.getProxyId();
    List<ReportProxy> records = table.getVisibleItems();
    int i = 0;
    for (ReportProxy record : records) {
      if (record != null && changedId.equals(record.stableId())) {
        List<ReportProxy> changedList = new ArrayList<ReportProxy>();
        changedList.add(record);
        table.setRowData(i + table.getPageStart(), changedList);
      }
      i++;
    }
  }

  public void setListener(Listener listener) {
    this.listener = listener;
  }

  /**
   * In this application, called by {@link ExpensesActivityMapper} each time a
   * ReportListPlace is posted. In a more typical set up, this would be a
   * constructor argument to a one shot activity, perhaps managing a shared
   * widget view instance.
   */
  public void updateForPlace(final ReportListPlace place) {
    this.place = place;
    if (running) {
      doUpdateForPlace();
    }
  }

  @UiFactory
  SimplePager createPager() {
    SimplePager p = new SimplePager(TextLocation.RIGHT);
    p.setDisplay(table);
    p.setRangeLimited(true);
    return p;
  }

  void onCancel() {
    onStop();
  }

  void onStop() {
    running = false;
    refreshTimer.cancel();
  }

  void start(AcceptsOneWidget panel, EventBus eventBus) {
    running = true;
    doUpdateForPlace();

    EntityProxyChange.registerForProxyType(eventBus, ReportProxy.class, this);
    requestReports(false);
    panel.setWidget(this);
  }

  /**
   * Add a sortable column to the table.
   * 
   * @param <C> the data type for the column
   * @param text the header text
   * @param cell the cell used to render the column
   * @param getter the getter to retrieve the value for the column
   * @param property the property to sort by
   * @return the column
   */
  private <C> Column<ReportProxy, C> addColumn(final String text,
      final Cell<C> cell, final GetValue<ReportProxy, C> getter,
      final String property) {
    final Column<ReportProxy, C> column = new Column<ReportProxy, C>(cell) {
      @Override
      public C getValue(ReportProxy object) {
        return getter.getValue(object);
      }
    };
    final SortableHeader header = new SortableHeader(text);
    allHeaders.add(header);

    // Sort created by default.
    if ("created".equals(property)) {
      header.setSorted(true);
      header.setReverseSort(true);
      orderBy = "created" + " DESC";
    }

    header.setUpdater(new ValueUpdater<String>() {
      public void update(String value) {
        header.setSorted(true);
        header.toggleReverseSort();

        for (SortableHeader otherHeader : allHeaders) {
          if (otherHeader != header) {
            otherHeader.setSorted(false);
            otherHeader.setReverseSort(true);
          }
        }
        table.redrawHeaders();

        // Request sorted rows.
        orderBy = property;
        if (header.getReverseSort()) {
          orderBy += " DESC";
        }
        searchBox.resetDefaultText();
        searchRegExp = null;

        // Go to the first page of the newly-sorted results
        pager.firstPage();
        requestReports(false);
      }
    });
    table.addColumn(column, header);
    return column;
  }

  /**
   * Create the {@link CellTable}.
   */
  private void createTable() {
    CellTable.Resources resources = GWT.create(TableResources.class);
    table = new CellTable<ReportProxy>(20, resources);
    table.setKeyboardSelectionPolicy(KeyboardSelectionPolicy.DISABLED);
    Styles.Common common = Styles.common();
    table.addColumnStyleName(0, common.spacerColumn());
    table.addColumnStyleName(1, common.expenseListPurposeColumn());
    table.addColumnStyleName(3, common.expenseListDepartmentColumn());
    table.addColumnStyleName(4, common.expenseListCreatedColumn());
    table.addColumnStyleName(5, common.spacerColumn());

    // Add a selection model.
    final NoSelectionModel<ReportProxy> selectionModel = new NoSelectionModel<ReportProxy>();
    table.setSelectionModel(selectionModel);
    selectionModel.addSelectionChangeHandler(new SelectionChangeEvent.Handler() {
      public void onSelectionChange(SelectionChangeEvent event) {
        Object selected = selectionModel.getLastSelectedObject();
        if (selected != null && listener != null) {
          listener.onReportSelected((ReportProxy) selected);
        }
      }
    });

    // Spacer column.
    table.addColumn(new SpacerColumn<ReportProxy>());

    // Purpose column.
    addColumn("Purpose", new HighlightCell(),
        new GetValue<ReportProxy, String>() {
          public String getValue(ReportProxy object) {
            return object.getPurpose();
          }
        }, "purpose");

    // Notes column.
    addColumn("Notes", new HighlightCell(),
        new GetValue<ReportProxy, String>() {
          public String getValue(ReportProxy object) {
            return object.getNotes();
          }
        }, "notes");

    // Department column.
    addColumn("Department", new TextCell(),
        new GetValue<ReportProxy, String>() {
          public String getValue(ReportProxy object) {
            return object.getDepartment();
          }
        }, "department");

    // Created column.
    addColumn("Created", new DateCell(DateTimeFormat.getFormat("MMM dd yyyy")),
        new GetValue<ReportProxy, Date>() {
          public Date getValue(ReportProxy object) {
            return object.getCreated();
          }
        }, "created");

    // Spacer column.
    table.addColumn(new SpacerColumn<ReportProxy>());
  }

  private void doUpdateForPlace() {
    if (place.getEmployeeId() == null) {
      findDepartmentOrEmployee(place.getDepartment(), null);
    } else {
      requestFactory.find(place.getEmployeeId()).fire(
          new Receiver<EmployeeProxy>() {
            @Override
            public void onSuccess(EmployeeProxy response) {
              findDepartmentOrEmployee("", response);
            }
          });
    }
  }

  /**
   * Set the current department and employee to filter on.
   * 
   * @param department the department, or null if none selected
   * @param employee the employee, or null if none selected
   */
  private void findDepartmentOrEmployee(String department,
      EmployeeProxy employee) {
    this.department = department;
    this.employee = employee;
    isCountStale = true;
    searchBox.resetDefaultText();
    startsWithSearch = null;
    breadcrumb.setInnerText(getBreadcrumb(department, employee));
    searchRegExp = null;
    pager.setPageStart(0);
    requestReports(false);
  }

  /**
   * Send a request for reports in the current range.
   * 
   * @param isPolling true if this request is caused by polling
   */
  private void requestReports(boolean isPolling) {
    // Cancel the refresh timer.
    refreshTimer.cancel();

    // Early exit if we don't have a request factory to request from.
    if (requestFactory == null) {
      return;
    }

    // Clear the known keys.
    if (!isPolling) {
      knownReportKeys = null;
    }

    // Get the parameters.
    String startsWith = startsWithSearch;
    if (startsWith == null || searchBox.getDefaultText().equals(startsWith)) {
      startsWith = "";
    }
    Range range = table.getVisibleRange();
    Long employeeId = employee == null ? -1 : new Long(employee.getId());
    String dept = department == null ? "" : department;

    // If a search string is specified, the results will not be sorted.
    if (startsWith.length() > 0) {
      for (SortableHeader header : allHeaders) {
        header.setSorted(false);
        header.setReverseSort(false);
      }
      table.redrawHeaders();
    }

    // Request the total data size.
    if (isCountStale) {
      isCountStale = false;
      if (!isPolling) {
        pager.startLoading();
      }
      lastDataSizeReceiver = new Receiver<Long>() {
        @Override
        public void onSuccess(Long response) {
          if (this == lastDataSizeReceiver) {
            int count = response.intValue();
            // Treat count == 1000 as inexact due to AppEngine limitation
            table.setRowCount(count, count != 1000);
          }
        }
      };
      requestFactory.reportRequest().countReportsBySearch(employeeId, dept,
          startsWith).fire(lastDataSizeReceiver);
    }

    // Request reports in the current range.
    lastDataReceiver = new Receiver<List<ReportProxy>>() {
      @Override
      public void onSuccess(List<ReportProxy> newValues) {
        if (this == lastDataReceiver) {
          int size = newValues.size();
          if (size < table.getPageSize()) {
            // Now we know the exact data size
            table.setRowCount(table.getPageStart() + size, true);
          }
          if (size > 0) {
            table.setRowData(table.getPageStart(), newValues);
          }

          // Add the new keys to the known keys.
          boolean isInitialData = knownReportKeys == null;
          if (knownReportKeys == null) {
            knownReportKeys = new HashSet<Object>();
          }
          for (ReportProxy value : newValues) {
            Object key = keyProvider.getKey(value);
            if (!isInitialData && !knownReportKeys.contains(key)) {
              new PhaseAnimation.CellTablePhaseAnimation<ReportProxy>(table,
                  value, keyProvider).run();
            }
            knownReportKeys.add(key);
          }
        }
        refreshTimer.schedule(REFRESH_INTERVAL);
      }
    };

    requestFactory.reportRequest().findReportEntriesBySearch(employeeId, dept,
        startsWith, orderBy, range.getStart(), range.getLength()).with(
        reportColumns).fire(lastDataReceiver);
  }

  /**
   * Search based on the search box text.
   */
  private void search() {
    isCountStale = true;
    startsWithSearch = searchBox.getText();
    requestReports(false);
  }
}
