/*
 * 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.
 */

#import <Foundation/Foundation.h>
#import "WXSectionDataController.h"

@interface WXRecyclerDataController : NSObject

@property (nonatomic, strong, readonly) NSArray<WXSectionDataController *> *sections;

- (void)updateData:(NSArray<WXSectionDataController *> *)newData;

- (NSInteger)numberOfSections;

- (NSInteger)numberOfItemsInSection:(NSInteger)section;

- (UIView *)cellForItemAtIndexPath:(NSIndexPath *)indexPath;

- (CGSize)sizeForItemAtIndexPath:(NSIndexPath *)indexPath;

- (UIView *)viewForHeaderAtIndexPath:(NSIndexPath *)indexPath;

- (CGSize)sizeForHeaderAtIndexPath:(NSIndexPath *)indexPath;

- (BOOL)isStickyForHeaderAtIndexPath:(NSIndexPath *)indexPath;

- (BOOL)hasHeaderInSection:(NSInteger)section;

- (NSIndexPath *)indexPathForCell:(WXCellComponent *)cell;

- (NSUInteger)indexForHeader:(WXHeaderComponent *)header;

@end
