/*
 * 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.tsfile.read.reader.chunk;

import org.apache.tsfile.common.conf.TSFileDescriptor;
import org.apache.tsfile.encoding.decoder.Decoder;
import org.apache.tsfile.enums.TSDataType;
import org.apache.tsfile.file.metadata.enums.TSEncoding;
import org.apache.tsfile.read.common.BatchData;
import org.apache.tsfile.read.filter.basic.Filter;
import org.apache.tsfile.read.reader.IChunkReader;
import org.apache.tsfile.read.reader.IPageReader;

import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
import java.util.function.LongConsumer;

public abstract class AbstractChunkReader implements IChunkReader {

  protected final Decoder defaultTimeDecoder =
      Decoder.getDecoderByType(
          TSEncoding.valueOf(TSFileDescriptor.getInstance().getConfig().getTimeEncoder()),
          TSDataType.INT64);

  protected final long readStopTime;

  // any filter, no matter value filter or time filter
  protected final Filter queryFilter;

  protected LongConsumer filterRowsRecorder;

  protected final List<IPageReader> pageReaderList = new LinkedList<>();

  protected AbstractChunkReader(long readStopTime, Filter filter, LongConsumer filterRowsRecorder) {
    this.readStopTime = readStopTime;
    this.queryFilter = filter;
    this.filterRowsRecorder = filterRowsRecorder;
  }

  /** judge if has next page whose page header satisfies the filter. */
  @Override
  public boolean hasNextSatisfiedPage() {
    return !pageReaderList.isEmpty();
  }

  /**
   * get next data batch.
   *
   * @return next data batch
   * @throws IOException IOException
   */
  @Override
  public BatchData nextPageData() throws IOException {
    if (pageReaderList.isEmpty()) {
      throw new IOException("No more page");
    }
    return pageReaderList.remove(0).getAllSatisfiedPageData();
  }

  @Override
  public void close() {
    // do nothing
  }

  @Override
  public List<IPageReader> loadPageReaderList() {
    return pageReaderList;
  }

  @Override
  public void markDataTypeModifiedAndCannotUseStatistics() {
    // In all implementations for now, pageReaderList is completed during construction.
    // In other cases, this method should be overridden.
    for (IPageReader iPageReader : pageReaderList) {
      iPageReader.setModified(true);
    }
  }
}
