/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 org.apache.myfaces.tobago.model;

import org.apache.myfaces.tobago.event.SortActionEvent;
import org.apache.myfaces.tobago.internal.util.StringUtils;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

public class SheetState implements Serializable, ScrollPositionState {

  private static final long serialVersionUID = 2L;

  private int first;
  private String sortedColumnId;
  private boolean ascending;
  private boolean toBeSorted;
  private List<Integer> columnWidths;
  private List<Integer> selectedRows;
  private ScrollPosition scrollPosition;
  private ExpandedState expandedState;
  private SelectedState selectedState;

  public SheetState() {
    reset();
  }

  public void reset() {
    first = -1;
    sortedColumnId = null;
    ascending = true;
    toBeSorted = false;
    columnWidths = new ArrayList<>();
    resetSelected();
    if (expandedState != null) {
      expandedState.reset();
    }
    if (selectedState != null) {
      selectedState.clear();
    }
    if (scrollPosition != null) {
      scrollPosition.clear();
    } else {
      scrollPosition = new ScrollPosition();
    }
  }

  public void resetSelected() {
    selectedRows = new ArrayList<>();
  }

  public List<Integer> getSelectedRows() {
    return selectedRows;
  }

  public void setSelectedRows(final List<Integer> selectedRows) {
    assert selectedRows != null;
    this.selectedRows = selectedRows;
  }

  public String getSortedColumnId() {
    return sortedColumnId;
  }

  public void setSortedColumnId(final String sortedColumnId) {
    if (StringUtils.notEquals(this.sortedColumnId, sortedColumnId)) {
      this.sortedColumnId = sortedColumnId;
      toBeSorted = true;
    }
  }

  public boolean isAscending() {
    return ascending;
  }

  public void setAscending(final boolean ascending) {
    if (this.ascending != ascending) {
      this.ascending = ascending;
      toBeSorted = true;
    }
  }

  public List<Integer> getColumnWidths() {
    return columnWidths;
  }

  public void setColumnWidths(final List<Integer> columnWidths) {
    this.columnWidths = columnWidths;
  }

  public boolean isDefinedColumnWidths() {
    for (final Integer columnWidth : columnWidths) {
      if (columnWidth < 0) {
        return false;
      }
    }
    return columnWidths.size() > 0;
  }

  public int getFirst() {
    return first;
  }

  public void setFirst(final int first) {
    this.first = first;
  }

  /**
   * @deprecated since 4.2.0, please use {@link #updateSortState(String id)}
   */
  @Deprecated
  public void updateSortState(final SortActionEvent sortEvent) {
    updateSortState(sortEvent.getColumn().getId());
  }

  public void updateSortState(final String columnId) {
    if (columnId.equals(sortedColumnId)) {
      setAscending(!isAscending());
    } else {
      setAscending(true);
      setSortedColumnId(columnId);
    }
  }

  public void resetSortState() {
    setAscending(true);
    setSortedColumnId(null);
  }

  @Override
  public ScrollPosition getScrollPosition() {
    return scrollPosition;
  }

  public void setScrollPosition(final ScrollPosition scrollPosition) {
    this.scrollPosition = scrollPosition;
  }

  public ExpandedState getExpandedState() {
    if (expandedState == null) {
      expandedState = new ExpandedState(2);
    }
    return expandedState;
  }

  public void setExpandedState(final ExpandedState expandedState) {
    this.expandedState = expandedState;
  }

  public SelectedState getSelectedState() {
    if (selectedState == null) {
      selectedState = new SelectedState();
    }
    return selectedState;
  }

  public void setSelectedState(final SelectedState selectedState) {
    this.selectedState = selectedState;
  }

  public boolean isToBeSorted() {
    return toBeSorted;
  }

  public void setToBeSorted(final boolean toBeSorted) {
    this.toBeSorted = toBeSorted;
  }
}
