/*
 * Copyright 2008 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.user.datepicker.client;

import com.google.gwt.aria.client.Roles;
import com.google.gwt.aria.client.SelectedValue;
import com.google.gwt.user.client.ui.HTMLTable.CellFormatter;
import com.google.gwt.user.datepicker.client.DefaultCalendarView.CellGrid.DateCell;

import java.util.Date;

/**
 * Simple calendar view. Not extensible as we wish to evolve it freely over
 * time.
 */

@SuppressWarnings(/* Date manipulation required */{"deprecation"})
public final class DefaultCalendarView extends CalendarView {

  /**
   * Cell grid.
   */
  // Javac bug requires that date be fully specified here.
  class CellGrid extends CellGridImpl<java.util.Date> {
    /**
     * A cell representing a date.
     */
    class DateCell extends Cell {
      private String cellStyle;
      private String dateStyle;

      DateCell(boolean isWeekend) {
        super(new Date());
        cellStyle = css().day();

        if (isWeekend) {
          cellStyle += " " + css().dayIsWeekend();
        }
        getElement().setTabIndex(isFiller() ? -1 : 0);
        setAriaSelected(false);
      }

      @Override
      public void addStyleName(String styleName) {
        if (dateStyle.indexOf(" " + styleName + " ") == -1) {
          dateStyle += styleName + " ";
        }
        updateStyle();
      }

      public boolean isFiller() {
        return !getModel().isInCurrentMonth(getValue());
      }

      @Override
      public void onHighlighted(boolean highlighted) {
        setHighlightedDate(getValue());
        updateStyle();
      }

      @Override
      public void onSelected(boolean selected) {
        if (selected) {
          getDatePicker().setValue(getValue(), true);
          if (isFiller()) {
            getDatePicker().setCurrentMonth(getValue());
          }
        }
        updateStyle();
      }

      @Override
      public void removeStyleName(String styleName) {
        dateStyle = dateStyle.replace(" " + styleName + " ", " ");
        updateStyle();
      }

      public void setAriaSelected(boolean value) {
        Roles.getGridcellRole().setAriaSelectedState(getElement(), SelectedValue.of(value));
      }

      @Override
      public void updateStyle() {

        String accum = dateStyle;

        if (isHighlighted()) {
          accum += " " + css().dayIsHighlighted();

          if (isHighlighted() && isSelected()) {
            accum += " " + css().dayIsValueAndHighlighted();
          }
        }
        if (!isEnabled()) {
          accum += " " + css().dayIsDisabled();
        }
        setStyleName(accum);
      }

      void update(Date current) {
        setEnabled(true);
        getValue().setTime(current.getTime());
        String value = getModel().formatDayOfMonth(getValue());
        setText(value);
        dateStyle = cellStyle;
        if (isFiller()) {
          getElement().setTabIndex(-1);
          dateStyle += " " + css().dayIsFiller();
        } else {
          getElement().setTabIndex(0);
          String extraStyle = getDatePicker().getStyleOfDate(current);
          if (extraStyle != null) {
            dateStyle += " " + extraStyle;
          }
        }
        // We want to certify that all date styles have " " before and after
        // them for ease of adding to and replacing them.
        dateStyle += " ";
        updateStyle();
      }

      private void setText(String value) {
        getElement().setInnerText(value);
      }
    }

    CellGrid() {
      resize(CalendarModel.WEEKS_IN_MONTH + 1, CalendarModel.DAYS_IN_WEEK);
    }

    @Override
    protected void onSelected(Cell lastSelected, Cell cell) {
    }
  }

  private CellGrid grid = new CellGrid();

  private Date firstDisplayed;

  private Date lastDisplayed = new Date();

  private DateCell ariaSelectedCell;

  /**
   * Constructor.
   */
  public DefaultCalendarView() {
  }

  @Override
  public void addStyleToDate(String styleName, Date date) {
    assert getDatePicker().isDateVisible(date) : "You tried to add style " + styleName + " to "
        + date + ". The calendar is currently showing " + getFirstDate()
        + " to " + getLastDate();
    getCell(date).addStyleName(styleName);
  }

  @Override
  public Date getFirstDate() {
    return firstDisplayed;
  }

  @Override
  public Date getLastDate() {
    return lastDisplayed;
  }

  @Override
  public boolean isDateEnabled(Date d) {
    return getCell(d).isEnabled();
  }

  @Override
  public void refresh() {
    firstDisplayed = getModel().getCurrentFirstDayOfFirstWeek();

    if (firstDisplayed.getDate() == 1) {
      // show one empty week if date is Monday is the first in month.
      addDays(firstDisplayed, -7);
    }

    lastDisplayed.setTime(firstDisplayed.getTime());

    for (int i = 0; i < grid.getNumCells(); i++) {
      if (i != 0) {
        addDays(lastDisplayed, 1);
      }
      DateCell cell = (DateCell) grid.getCell(i);
      cell.update(lastDisplayed);
    }
    setAriaSelectedCell(null);
  }

  private static void addDays(Date date, int days) {
    CalendarUtil.addDaysToDate(date, days);
    if (date.getHours() != 0) {
      // We hit DST transition, try reseting back so follow up days continue showing midnight:
      date.setHours(0);
    }
  }

  @Override
  public void removeStyleFromDate(String styleName, Date date) {
    getCell(date).removeStyleName(styleName);
  }

  @Override
  public void setAriaSelectedCell(Date date) {
    if (ariaSelectedCell != null) {
      ariaSelectedCell.setAriaSelected(false);
    }
    DateCell newSelectedCell = date != null ? getCell(date) : null;
    if (newSelectedCell != null) {
      newSelectedCell.setAriaSelected(true);
    }
    ariaSelectedCell = newSelectedCell;
  }

  @Override
  public void setEnabledOnDate(boolean enabled, Date date) {
    getCell(date).setEnabled(enabled);
  }

  @Override
  public void setup() {
    // Preparation
    CellFormatter formatter = grid.getCellFormatter();
    int weekendStartColumn = -1;
    int weekendEndColumn = -1;

    // Set up the day labels.
    for (int i = 0; i < CalendarModel.DAYS_IN_WEEK; i++) {
      int shift = CalendarUtil.getStartingDayOfWeek();
      int dayIdx = i + shift < CalendarModel.DAYS_IN_WEEK ? i + shift : i
          + shift - CalendarModel.DAYS_IN_WEEK;
      grid.setText(0, i, getModel().formatDayOfWeek(dayIdx));

      if (CalendarUtil.isWeekend(dayIdx)) {
        formatter.setStyleName(0, i, css().weekendLabel());
        if (weekendStartColumn == -1) {
          weekendStartColumn = i;
        } else {
          weekendEndColumn = i;
        }
      } else {
        formatter.setStyleName(0, i, css().weekdayLabel());
      }
    }

    // Set up the calendar grid.
    for (int row = 1; row <= CalendarModel.WEEKS_IN_MONTH; row++) {
      for (int column = 0; column < CalendarModel.DAYS_IN_WEEK; column++) {
        DateCell cell = grid.new DateCell(column == weekendStartColumn
            || column == weekendEndColumn);
        grid.setWidget(row, column, cell);
      }
    }
    initWidget(grid);
    grid.setStyleName(css().days());
  }

  private DateCell getCell(Date d) {
    int index = CalendarUtil.getDaysBetween(firstDisplayed, d);
    if (index < 0 || grid.getNumCells() <= index) {
      return null;
    }

    DateCell cell = (DateCell) grid.getCell(index);
    if (cell.getValue().getDate() != d.getDate()) {
      throw new IllegalStateException(d + " cannot be associated with cell "
          + cell + " as it has date " + cell.getValue());
    }
    return cell;
  }
}
