text:
//
//  HXPhotoView.m
//  HXPhotoPickerExample
//
//  Created by Silence on 17/2/17.
//  Copyright © 2017年 Silence. All rights reserved.
//

#import "HXPhotoView.h"
#import "UIView+HXExtension.h"
#import <MobileCoreServices/MobileCoreServices.h>
#import <MediaPlayer/MediaPlayer.h>
#import "UIImage+HXExtension.h"
#import "HXAlbumListViewController.h"
#import "HXPhotoPreviewViewController.h"
#import "HXCustomNavigationController.h"
#import "HXCustomCameraViewController.h"
#import "HXPhotoViewController.h"
#import "HXPhotoBottomSelectView.h"
#import "UIColor+HXExtension.h"

@interface HXPhotoView ()<HXCollectionViewDataSource,HXCollectionViewDelegate, UICollectionViewDelegateFlowLayout,HXPhotoSubViewCellDelegate,UIAlertViewDelegate,HXAlbumListViewControllerDelegate,HXCustomCameraViewControllerDelegate,HXPhotoPreviewViewControllerDelegate, HXPhotoViewControllerDelegate, HXCustomNavigationControllerDelegate>
@property (strong, nonatomic) NSMutableArray *dataList;
@property (strong, nonatomic) NSMutableArray *photos;
@property (strong, nonatomic) NSMutableArray *videos;
@property (strong, nonatomic) HXPhotoModel *addModel;
@property (assign, nonatomic) BOOL isAddModel;
@property (assign, nonatomic) BOOL original;
@property (strong, nonatomic) UICollectionViewFlowLayout *flowLayout;
@property (assign, nonatomic) NSInteger numOfLinesOld;
@property (assign, nonatomic) BOOL downLoadComplete;
@property (strong, nonatomic) UIImage *tempCameraImage;
@property (strong, nonatomic) UIImagePickerController* imagePickerController;
@property (strong, nonatomic) HXPhotoSubViewCell *addCell;
@property (assign, nonatomic) BOOL tempShowAddCell;
@property (assign, nonatomic) CGFloat lastWidth;
@end

@implementation HXPhotoView
@synthesize addImageName = _addImageName;
@synthesize addDarkImageName = _addDarkImageName;
@synthesize manager = _manager;

- (UICollectionViewFlowLayout *)flowLayout {
    if (!_flowLayout) {
        _flowLayout = [[UICollectionViewFlowLayout alloc] init];
        _flowLayout.scrollDirection = self.scrollDirection;
    }
    return _flowLayout;
}

- (NSMutableArray *)dataList {
    if (!_dataList) {
        _dataList = [NSMutableArray array];
    }
    return _dataList;
}
- (HXPhotoModel *)addModel {
    if (!_addModel) {
        _addModel = [[HXPhotoModel alloc] init];
        _addModel.type = HXPhotoModelMediaTypeCamera;
        _addModel.thumbPhoto = [UIImage hx_imageNamed:self.addImageName];
        _addModel.previewPhoto = [UIImage hx_imageNamed:self.addDarkImageName];
    }
    return _addModel;
}
- (HXPhotoManager *)manager {
    if (!_manager) {
        _manager = [[HXPhotoManager alloc] init];
    }
    return _manager;
}
+ (instancetype)photoManager:(HXPhotoManager *)manager {
    return [[self alloc] initWithManager:manager];
}
+ (instancetype)photoManager:(HXPhotoManager *)manager scrollDirection:(UICollectionViewScrollDirection)scrollDirection {
    return [[self alloc] initWithManager:manager scrollDirection:scrollDirection];
}
- (instancetype)initWithCoder:(NSCoder *)coder {
    if (self = [super initWithCoder:coder]) {
        [self setup];
    }
    return self;
}
- (instancetype)initWithFrame:(CGRect)frame manager:(HXPhotoManager *)manager {
    return [self initWithFrame:frame manager:manager scrollDirection:UICollectionViewScrollDirectionVertical];
}
- (instancetype)initWithFrame:(CGRect)frame manager:(HXPhotoManager *)manager scrollDirection:(UICollectionViewScrollDirection)scrollDirection {
    self = [super initWithFrame:frame];
    if (self) {
        self.scrollDirection = scrollDirection;
        _manager = manager;
        [self setup];
    }
    return self;
}
- (instancetype)initWithManager:(HXPhotoManager *)manager {
    return [self initWithManager:manager scrollDirection:UICollectionViewScrollDirectionVertical];
}
- (instancetype)initWithManager:(HXPhotoManager *)manager scrollDirection:(UICollectionViewScrollDirection)scrollDirection {
    self = [super init];
    if (self) {
        self.scrollDirection = scrollDirection;
        _manager = manager;
        [self setup];
    }
    return self;
}
- (instancetype)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        [self setup];
    }
    return self;
}
- (void)awakeFromNib {
    [super awakeFromNib];
    [self setup];
}
- (HXCollectionView *)collectionView {
    if (!_collectionView) {
        _collectionView = [[HXCollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:self.flowLayout];
        if (self.scrollDirection != UICollectionViewScrollDirectionHorizontal) {
            _collectionView.scrollEnabled = NO;
        }
        _collectionView.dataSource = self;
        _collectionView.delegate = self;
        _collectionView.backgroundColor = self.backgroundColor;
        [_collectionView registerClass:[HXPhotoSubViewCell class] forCellWithReuseIdentifier:@"HXPhotoSubViewCellId"];
        [_collectionView registerClass:[HXPhotoSubViewCell class] forCellWithReuseIdentifier:@"addCell"];
    }
    return _collectionView;
}
- (NSInteger)lineCount {
    if (!_lineCount) {
        _lineCount = 3;
    }
    return _lineCount;
}
- (void)setScrollDirection:(UICollectionViewScrollDirection)scrollDirection {
    _scrollDirection = scrollDirection;
    if (scrollDirection == UICollectionViewScrollDirectionHorizontal) {
        self.collectionView.scrollEnabled = YES;
    }else {
        self.collectionView.scrollEnabled = NO;
    }
    self.flowLayout.scrollDirection = scrollDirection;
}
- (void)setBackgroundColor:(UIColor *)backgroundColor {
    self.collectionView.backgroundColor = backgroundColor;
    [super setBackgroundColor:backgroundColor];
}
- (void)setup {
    self.maximumHeight = HX_ScreenHeight;
    self.lastWidth = 0;
    if (_manager) {
        _manager.configuration.specialModeNeedHideVideoSelectBtn = YES;
    }
    self.spacing = 3;
    self.lineCount = 3;
    self.numOfLinesOld = 0;
    self.tag = 9999;
    _showAddCell = YES;
    self.tempShowAddCell = YES;
    self.previewShowBottomPageControl = YES;
    self.adaptiveDarkness = YES;

    self.flowLayout.minimumLineSpacing = self.spacing;
    self.flowLayout.minimumInteritemSpacing = self.spacing;
    [self addSubview:self.collectionView];

    if (_manager.afterSelectedArray.count > 0) {
        if ([self.delegate respondsToSelector:@selector(photoListViewControllerDidDone:allList:photos:videos:original:)]) {
            [self.delegate photoListViewControllerDidDone:self allList:self.manager.afterSelectedArray.copy photos:self.manager.afterSelectedPhotoArray.copy videos:self.manager.afterSelectedVideoArray.copy original:self.manager.afterOriginal];
        }
        [self setupDataWithAllList:self.manager.afterSelectedArray.copy photos:self.manager.afterSelectedPhotoArray.copy videos:self.manager.afterSelectedVideoArray.copy original:self.manager.afterOriginal];
    }

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(refreshView) name:@"HXPhotoViewNeedReloadNotification" object:nil];
}
- (void)jumpPreviewViewControllerWithModel:(HXPhotoModel *)model {
    if (![self.manager.afterSelectedArray containsObject:model]) {
        NSSLog(@"model有误!!!");
        return;
    }
    HXPhotoPreviewViewController *vc = [[HXPhotoPreviewViewController alloc] init];
    vc.disableaPersentInteractiveTransition = self.disableaInteractiveTransition;
    vc.outside = YES;
    vc.manager = self.manager;
    vc.exteriorPreviewStyle = self.previewStyle;
    vc.delegate = self;
    vc.modelArray = [NSMutableArray arrayWithArray:self.manager.afterSelectedArray];
    vc.currentModelIndex = [self.manager.afterSelectedArray indexOfObject:model];
    vc.previewShowDeleteButton = self.previewShowDeleteButton;
    vc.showBottomPageControl = self.previewShowBottomPageControl;
    vc.photoView = self;
    vc.modalPresentationStyle = UIModalPresentationOverFullScreen;
    vc.modalPresentationCapturesStatusBarAppearance = YES;
    [[self hx_viewController] presentViewController:vc animated:YES completion:nil];
}
- (void)jumpPreviewViewControllerWithIndex:(NSInteger)index {
    if (index >= 0 && index < self.manager.afterSelectedArray.count) {
        HXPhotoModel *model = self.manager.afterSelectedArray[index];
        [self jumpPreviewViewControllerWithModel:model];
    }else {
        NSSLog(@"越界啦!!!");
    }
}
- (HXPhotoSubViewCell *)previewingContextViewWithPoint:(CGPoint)point {
    CGPoint cPoint = [self convertPoint:point toView:self.collectionView];
    NSIndexPath *indexPath = [self.collectionView indexPathForItemAtPoint:cPoint];
    if (indexPath) {
        HXPhotoSubViewCell *cell = (HXPhotoSubViewCell *)[self.collectionView cellForItemAtIndexPath:indexPath];
        if (cell.model.type == HXPhotoModelMediaTypeCamera) {
            return nil;
        }
        return cell;
    }
    return nil;
}
- (HXPhotoSubViewCell *)collectionViewCellWithIndex:(NSInteger)index {
    if (index < 0 || index > self.dataList.count - 1 || !self.dataList.count) {
        return nil;
    }
    HXPhotoSubViewCell *cell = (HXPhotoSubViewCell *)[self.collectionView cellForItemAtIndexPath:[NSIndexPath indexPathForItem:index inSection:0]];
    if (cell.model.type == HXPhotoModelMediaTypeCamera) {
        return nil;
    }
    return cell;
}
- (void)setEditEnabled:(BOOL)editEnabled {
    _editEnabled = editEnabled;
    self.collectionView.editEnabled = editEnabled;
}

- (void)setManager:(HXPhotoManager *)manager {
    _manager = manager;
    manager.configuration.specialModeNeedHideVideoSelectBtn = YES;
    if (self.manager.afterSelectedArray.count > 0) {
        if ([self.delegate respondsToSelector:@selector(photoListViewControllerDidDone:allList:photos:videos:original:)]) {
            [self.delegate photoListViewControllerDidDone:self allList:self.manager.afterSelectedArray.copy photos:self.manager.afterSelectedPhotoArray.copy videos:self.manager.afterSelectedVideoArray.copy original:self.manager.afterOriginal];
        }
        [self setupDataWithAllList:self.manager.afterSelectedArray.copy photos:self.manager.afterSelectedPhotoArray.copy videos:self.manager.afterSelectedVideoArray.copy original:self.manager.afterOriginal];
    }
}

- (void)setHideDeleteButton:(BOOL)hideDeleteButton {
    _hideDeleteButton = hideDeleteButton;
    [self.collectionView reloadData];
}
- (void)setShowAddCell:(BOOL)showAddCell {
    _showAddCell = showAddCell;
    self.tempShowAddCell = showAddCell;
    if (self.manager.afterSelectedArray.count > 0) {
        [self setupDataWithAllList:self.manager.afterSelectedArray.copy photos:self.manager.afterSelectedPhotoArray.copy videos:self.manager.afterSelectedVideoArray.copy original:self.manager.afterOriginal];
    }
}
- (NSString *)addImageName {
    if (!_addImageName) {
        _addImageName = @"hx_list_add_img";
    }
    return _addImageName;
}
- (NSString *)addDarkImageName {
    if (!_addDarkImageName) {
        _addDarkImageName = @"hx_list_add_dark_img";
    }
    return _addDarkImageName;
}
- (void)setAddImageName:(NSString *)addImageName {
    _addImageName = addImageName;
    self.addModel.thumbPhoto = [UIImage hx_imageNamed:addImageName];
    if (self.tempShowAddCell) {
        [self.collectionView reloadData];
    }
}
- (void)setAddDarkImageName:(NSString *)addDarkImageName {
    _addDarkImageName = addDarkImageName;
    self.addModel.previewPhoto = [UIImage hx_imageNamed:addDarkImageName];
    if (self.tempShowAddCell) {
        [self.collectionView reloadData];
    }
}
- (void)setDeleteImageName:(NSString *)deleteImageName {
    _deleteImageName = deleteImageName;
    [self.collectionView reloadData];
}
/**
 刷新视图
 */
- (void)refreshView {
    if (!self.manager.configuration.singleSelected) {
        [self setupDataWithAllList:self.manager.afterSelectedArray.copy photos:self.manager.afterSelectedPhotoArray.copy videos:self.manager.afterSelectedVideoArray.copy original:self.manager.afterOriginal];
    }
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
    return self.tempShowAddCell ? self.dataList.count + 1 : self.dataList.count;
}
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
    return 1;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
    if (self.tempShowAddCell) {
        if (indexPath.item == self.dataList.count) {
            HXPhotoSubViewCell *addCell = [collectionView dequeueReusableCellWithReuseIdentifier:@"addCell" forIndexPath:indexPath];
            addCell.index = indexPath.item;
            addCell.model = self.addModel;
            return addCell;
        }
    }
    HXPhotoSubViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"HXPhotoSubViewCellId" forIndexPath:indexPath];
    cell.index = indexPath.item;
    cell.customProtocol = self.cellCustomProtocol;
    cell.delegate = self;
    cell.canEdit = self.collectionView.editEnabled;
    if (self.deleteImageName) {
        cell.deleteImageName = self.deleteImageName;
    }
    cell.model = self.dataList[indexPath.item];
    cell.showDeleteNetworkPhotoAlert = self.showDeleteNetworkPhotoAlert;
    cell.deleteCellShowAlert = self.deleteCellShowAlert;
    cell.hideDeleteButton = self.hideDeleteButton;
    return cell;
}

- (BOOL)collectionView:(UICollectionView *)collectionView shouldSelectItemAtIndexPath:(NSIndexPath *)indexPath {
    if (self.tempShowAddCell && indexPath.item == self.dataList.count) {
        return YES;
    }
    BOOL canSelect = YES;
    if ([self.delegate respondsToSelector:@selector(photoView:collectionViewShouldSelectItemAtIndexPath:model:)]) {
        HXPhotoModel *model = self.dataList[indexPath.item];
        canSelect = [self.delegate photoView:self collectionViewShouldSelectItemAtIndexPath:indexPath model:model];
    }
    return canSelect;
}
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
    if (self.tempShowAddCell) {
        if (indexPath.item == self.dataList.count) {
            if ([self.delegate respondsToSelector:@selector(photoViewDidAddCellClick:)]) {
                [self.delegate photoViewDidAddCellClick:self];
            }
            if (self.didAddCellBlock) {
                self.didAddCellBlock(self);
            }
            if (self.interceptAddCellClick) {
                return;
            }
            [self goPhotoViewController];
            return;
        }
    }
    self.currentIndexPath = indexPath;
    HXPhotoModel *model = self.dataList[indexPath.item];
    if (model.networkPhotoUrl) {
        if (model.downloadError) {
            HXPhotoSubViewCell *cell = (HXPhotoSubViewCell *)[self.collectionView cellForItemAtIndexPath:indexPath];
            [cell againDownload];
            return;
        }
    }
    if (model.type == HXPhotoModelMediaTypeCamera) {
        if ([self.delegate respondsToSelector:@selector(photoViewDidAddCellClick:)]) {
            [self.delegate photoViewDidAddCellClick:self];
        }
        if (self.didAddCellBlock) {
            self.didAddCellBlock(self);
        }
        if (self.interceptAddCellClick) {
            return;
        }
        [self goPhotoViewController];
    }else {
        HXPhotoPreviewViewController *vc = [[HXPhotoPreviewViewController alloc] init];
        vc.disableaPersentInteractiveTransition = self.disableaInteractiveTransition;
        vc.outside = YES;
        vc.manager = self.manager;
        vc.exteriorPreviewStyle = self.previewStyle;
        vc.delegate = self;
        vc.modelArray = [NSMutableArray arrayWithArray:self.dataList];
        vc.currentModelIndex = [self.dataList indexOfObject:model];
        vc.previewShowDeleteButton = self.previewShowDeleteButton;
        vc.showBottomPageControl = self.previewShowBottomPageControl;
        vc.photoView = self;
        vc.modalPresentationStyle = UIModalPresentationOverFullScreen;
        vc.modalPresentationCapturesStatusBarAppearance = YES;
        [[self hx_viewController] presentViewController:vc animated:YES completion:nil];
    }
}
#if HXPhotoViewCustomItemSize || HXPhotoViewCustomItemSizeEnable
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
    BOOL isAddItem = NO;
    if (self.tempShowAddCell && indexPath.item == self.dataList.count) {
        isAddItem =  YES;
    }
    CGSize size = CGSizeMake(100, 100);
    if ([self.delegate respondsToSelector:@selector(collectionView:layout:sizeForItemAtIndexPath:isAddItem:photoView:)]) {
        size = [self.delegate collectionView:collectionView layout:collectionViewLayout sizeForItemAtIndexPath:indexPath isAddItem:isAddItem photoView:self];
    }
    return size;
}
#endif
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section {
    if ([self.delegate respondsToSelector:@selector(collectionView:layout:minimumLineSpacingForSectionAtIndex:photoView:)]) {
        return [self.delegate collectionView:collectionView layout:collectionViewLayout minimumLineSpacingForSectionAtIndex:section photoView:self];
    }
    return self.spacing;
}
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section {
    if ([self.delegate respondsToSelector:@selector(collectionView:layout:minimumInteritemSpacingForSectionAtIndex:photoView:)]) {
        return [self.delegate collectionView:collectionView layout:collectionViewLayout minimumInteritemSpacingForSectionAtIndex:section photoView:self];
    }
    return self.spacing;
}

#pragma mark - < HXPhotoPreviewViewControllerDelegate >
- (void)photoPreviewControllerDidCancel:(HXPhotoPreviewViewController *)previewController model:(HXPhotoModel *)model {
    if ([self.delegate respondsToSelector:@selector(photoViewPreviewDismiss:)]) {
        [self.delegate photoViewPreviewDismiss:self];
    }
}
- (void)photoPreviewCellDownloadImageComplete:(HXPhotoPreviewViewController *)previewController model:(HXPhotoModel *)model {
    if (!model.loadOriginalImage) {
        NSIndexPath *indexPath = [self currentModelIndexPath:model];
        HXPhotoSubViewCell *cell = (HXPhotoSubViewCell *)[self.collectionView cellForItemAtIndexPath:indexPath];
        [cell resetNetworkImage];
    }
}
- (void)photoPreviewDidDeleteClick:(HXPhotoPreviewViewController *)previewController deleteModel:(HXPhotoModel *)model deleteIndex:(NSInteger)index {
    [self deleteModelWithIndex:index];
}
- (void)photoPreviewSelectLaterDidEditClick:(HXPhotoPreviewViewController *)previewController beforeModel:(HXPhotoModel *)beforeModel afterModel:(HXPhotoModel *)afterModel {
    if (self.manager.configuration.useWxPhotoEdit && afterModel.subType == HXPhotoModelMediaSubTypePhoto) {
        [self.collectionView reloadData];
        [self dragCellCollectionViewCellEndMoving:self.collectionView];
        return;
    }
    [self.manager afterSelectedArrayReplaceModelAtModel:beforeModel withModel:afterModel];
    [self.manager afterSelectedListAddEditPhotoModel:afterModel];

    [self.photos removeAllObjects];
    [self.videos removeAllObjects];
    NSInteger i = 0;
    for (HXPhotoModel *model in self.manager.afterSelectedArray) {
        model.selectIndexStr = [NSString stringWithFormat:@"%ld",i + 1];
        if (model.subType == HXPhotoModelMediaSubTypePhoto) {
            [self.photos addObject:model];
        }else if (model.subType == HXPhotoModelMediaSubTypeVideo) {
            [self.videos addObject:model];
        }
        i++;
    }
    [self.manager setAfterSelectedPhotoArray:self.photos];
    [self.manager setAfterSelectedVideoArray:self.videos];
    [self.dataList replaceObjectAtIndex:[self.dataList indexOfObject:beforeModel] withObject:afterModel];
    [self.collectionView reloadData];
    [self dragCellCollectionViewCellEndMoving:self.collectionView];
}

/**
 添加按钮点击事件
 */
- (void)goPhotoViewController {
    if (self.outerCamera) {
        HXPhotoBottomViewModel *shootingModel = [[HXPhotoBottomViewModel alloc] init];
        shootingModel.subTitleDarkColor = [UIColor hx_colorWithHexStr:@"#999999"];
        if (self.manager.type == HXPhotoManagerSelectedTypePhoto) {
            if (self.manager.configuration.photoMaxNum > 0) {
                self.manager.configuration.maxNum = self.manager.configuration.photoMaxNum;
            }
            shootingModel.title = [NSBundle hx_localizedStringForKey:@"拍照"];
        }else if (self.manager.type == HXPhotoManagerSelectedTypeVideo) {
            if (self.manager.configuration.videoMaxNum > 0) {
                self.manager.configuration.maxNum = self.manager.configuration.videoMaxNum;
            }
            shootingModel.title = [NSBundle hx_localizedStringForKey:@"摄像"];
        }else {
            shootingModel.title = [NSBundle hx_localizedStringForKey:@"拍摄"];
            if (self.manager.configuration.photoMaxNum > 0 &&
                self.manager.configuration.videoMaxNum > 0) {
                self.manager.configuration.maxNum = self.manager.configuration.videoMaxNum + self.manager.configuration.photoMaxNum;
            }
            if (!self.manager.configuration.selectTogether) {
                if (self.manager.afterSelectedPhotoArray.count) {
                    shootingModel.title = [NSBundle hx_localizedStringForKey:@"拍照"];
                }else if (self.manager.afterSelectedVideoArray.count) {
                    shootingModel.title = [NSBundle hx_localizedStringForKey:@"摄像"];
                }else {
                    shootingModel.subTitle = [NSBundle hx_localizedStringForKey:@"照片或视频"];
                    shootingModel.cellHeight = 65.f;
                }
            }else {
                shootingModel.subTitle = [NSBundle hx_localizedStringForKey:@"照片或视频"];
                shootingModel.cellHeight = 65.f;
            }
        }
        HXPhotoBottomViewModel *selectModel = [[HXPhotoBottomViewModel alloc] init];
        selectModel.title = [NSBundle hx_localizedStringForKey:@"从手机相册选择"];

        HXWeakSelf
        HXPhotoBottomSelectView *selectView = [HXPhotoBottomSelectView showSelectViewWithModels:@[shootingModel, selectModel] headerView:nil showTopLineView:NO cancelTitle:nil selectCompletion:^(NSInteger index, HXPhotoBottomViewModel * _Nonnull model) {
            if (index == 0) {
                [weakSelf goCameraViewController];
            }else if (index == 1) {
                [weakSelf directGoPhotoViewController];
            }
        } cancelClick:nil];
        selectView.adaptiveDarkness = self.adaptiveDarkness;
        return;
    }
    [self directGoPhotoViewController];
}

- (void)directGoPhotoViewController {
    HXCustomNavigationController *nav = [[HXCustomNavigationController alloc] initWithManager:self.manager delegate:self];
    nav.modalPresentationStyle = UIModalPresentationOverFullScreen;
    nav.modalPresentationCapturesStatusBarAppearance = YES;
    [[self hx_viewController] presentViewController:nav animated:YES completion:nil];
}
#pragma mark - < HXCustomNavigationControllerDelegate >
- (void)photoNavigationViewController:(HXCustomNavigationController *)photoNavigationViewController didDoneAllList:(NSArray<HXPhotoModel *> *)allList photos:(NSArray<HXPhotoModel *> *)photoList videos:(NSArray<HXPhotoModel *> *)videoList original:(BOOL)original {

    if ([self.delegate respondsToSelector:@selector(photoListViewControllerDidDone:allList:photos:videos:original:)]) {
        [self.delegate photoListViewControllerDidDone:self allList:allList photos:photoList videos:videoList original:original];
    }
    if ([self.delegate respondsToSelector:@selector(photoViewCurrentSelected:photos:videos:original:)]) {
        NSMutableArray *allModel = [NSMutableArray array];
        NSMutableArray *photoModels = [NSMutableArray array];
        NSMutableArray *videoModels = [NSMutableArray array];
        NSMutableArray *tempAll = allList.mutableCopy;
        for (HXPhotoModel *pModel in self.dataList) {
            for (HXPhotoModel *subPModel in tempAll) {
                if ([pModel isEqualToPhotoModel:subPModel]) {
                    [tempAll removeObject:subPModel];
                    break;
                }
            }
        }
        for (HXPhotoModel *photoModel in tempAll) {
            if (photoModel.subType == HXPhotoModelMediaSubTypePhoto) {
                [photoModels addObject:photoModel];
            }else if (photoModel.subType == HXPhotoModelMediaSubTypeVideo) {
                [videoModels addObject:photoModel];
            }
            [allModel addObject:photoModel];
        }
        [self.delegate photoViewCurrentSelected:allModel.copy photos:photoModels.copy videos:videoModels.copy original:original];
    }
    [self setupDataWithAllList:allList photos:photoList videos:videoList original:original];
}
- (void)photoNavigationViewControllerDidCancel:(HXCustomNavigationController *)photoNavigationViewController {
    if ([self.delegate respondsToSelector:@selector(photoViewDidCancel:)]) {
        [self.delegate photoViewDidCancel:self];
    }
    if (self.didCancelBlock) {
        self.didCancelBlock();
    }
}

/**
 前往相机
 */
- (void)goCameraViewController {
    if(![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
        [[self hx_viewController].view hx_showImageHUDText:[NSBundle hx_localizedStringForKey:@"无法使用相机!"]];
        return;
    }
    HXWeakSelf
    [AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {
        dispatch_async(dispatch_get_main_queue(), ^{
            if (granted) {
                if (weakSelf.manager.configuration.replaceCameraViewController) {
                    HXPhotoConfigurationCameraType cameraType;
                    if (weakSelf.manager.type == HXPhotoManagerSelectedTypePhoto) {
                        cameraType = HXPhotoConfigurationCameraTypePhoto;
                    }else if (weakSelf.manager.type == HXPhotoManagerSelectedTypeVideo) {
                        cameraType = HXPhotoConfigurationCameraTypeVideo;
                    }else {
                        if (!weakSelf.manager.configuration.selectTogether) {
                            if (weakSelf.manager.afterSelectedPhotoArray.count > 0) {
                                cameraType = HXPhotoConfigurationCameraTypePhoto;
                            }else if (weakSelf.manager.afterSelectedVideoArray.count > 0) {
                                cameraType = HXPhotoConfigurationCameraTypeVideo;
                            }else {
                                cameraType = HXPhotoConfigurationCameraTypePhotoAndVideo;
                            }
                        }else {
                            cameraType = HXPhotoConfigurationCameraTypePhotoAndVideo;
                        }
                    }
                    switch (weakSelf.manager.configuration.customCameraType) {
                        case HXPhotoCustomCameraTypePhoto:
                            cameraType = HXPhotoConfigurationCameraTypePhoto;
                            break;
                        case HXPhotoCustomCameraTypeVideo:
                            cameraType = HXPhotoConfigurationCameraTypeVideo;
                            break;
                        case HXPhotoCustomCameraTypePhotoAndVideo:
                            cameraType = HXPhotoConfigurationCameraTypePhotoAndVideo;
                            break;
                        default:
                            break;
                    }
                    if (weakSelf.manager.configuration.shouldUseCamera) {
                        weakSelf.manager.configuration.shouldUseCamera([weakSelf hx_viewController], cameraType, weakSelf.manager);
                    }
                    weakSelf.manager.configuration.useCameraComplete = ^(HXPhotoModel *model) {
                        [weakSelf customCameraViewController:nil didDone:model];
                    };
                    return;
                }
                HXCustomCameraViewController *vc = [[HXCustomCameraViewController alloc] init];
                vc.delegate = weakSelf;
                vc.manager = weakSelf.manager;
                vc.isOutside = YES;
                HXCustomNavigationController *nav = [[HXCustomNavigationController alloc] initWithRootViewController:vc];
                nav.isCamera = YES;
                nav.supportRotation = weakSelf.manager.configuration.supportRotation;
                nav.modalPresentationStyle = UIModalPresentationOverFullScreen;
                nav.modalPresentationCapturesStatusBarAppearance = YES;
                [[weakSelf hx_viewController] presentViewController:nav animated:YES completion:nil];
            }else {
                [HXPhotoTools showUnusableCameraAlert:weakSelf.hx_viewController];
            }
        });
    }];
}

- (void)customCameraViewController:(HXCustomCameraViewController *)viewController didDone:(HXPhotoModel *)model {
    [self cameraDidNextClick:model];
}
/**
 相机拍完之后的代理

 @param model 照片模型
 */
- (void)cameraDidNextClick:(HXPhotoModel *)model {
    // 判断类型
    if (self.manager.shouldSelectModel) {
        NSString *str = self.manager.shouldSelectModel(model);
        if (str) {
            [[self hx_viewController].view hx_showImageHUDText:str];
            return;
        }
    }
    if (model.subType == HXPhotoModelMediaSubTypePhoto) {
        if (self.manager.type == HXPhotoManagerSelectedTypeVideo) {
            [[self hx_viewController].view hx_showImageHUDText:[NSBundle hx_localizedStringForKey:@"图片不能和视频同时选择"]];
            return;
        }
        // 当选择图片个数没有达到最大个数时就添加到选中数组中
        if ([self.manager afterSelectPhotoCountIsMaximum]) {
            NSInteger maxCount = self.manager.configuration.photoMaxNum > 0 ? self.manager.configuration.photoMaxNum : self.manager.configuration.maxNum;
            [[self hx_viewController].view hx_showImageHUDText:[NSString stringWithFormat:[NSBundle hx_localizedStringForKey:@"最多只能选择%ld张图片"],maxCount]];
            return;
        }
    }else if (model.subType == HXPhotoModelMediaSubTypeVideo) {
        if (self.manager.type == HXPhotoManagerSelectedTypePhoto) {
            [[self hx_viewController].view hx_showImageHUDText:[NSBundle hx_localizedStringForKey:@"视频不能和图片同时选择"]];
            return;
        }
        // 当选中视频个数没有达到最大个数时就添加到选中数组中
        if (round(model.videoDuration) < self.manager.configuration.videoMinimumSelectDuration) {

            [[self hx_viewController].view hx_showImageHUDText:[NSString stringWithFormat:[NSBundle hx_localizedStringForKey:@"视频少于%ld秒,无法选择"], self.manager.configuration.videoMinimumSelectDuration]];
            return;
        }else if (round(model.videoDuration) >= self.manager.configuration.videoMaximumSelectDuration + 1) {
            [[self hx_viewController].view hx_showImageHUDText:[NSString stringWithFormat:[NSBundle hx_localizedStringForKey:@"视频大于%ld秒,无法选择"], self.manager.configuration.videoMaximumSelectDuration]];
            return;
        }else if ([self.manager afterSelectVideoCountIsMaximum]) {
            NSInteger maxCount = self.manager.configuration.videoMaxNum > 0 ? self.manager.configuration.videoMaxNum : self.manager.configuration.maxNum;
            [[self hx_viewController].view hx_showImageHUDText:[NSString stringWithFormat:[NSBundle hx_localizedStringForKey:@"最多只能选择%ld个视频"],maxCount]];
            return;
        }
    }
    [self.manager afterListAddCameraTakePicturesModel:model];
    if ([self.delegate respondsToSelector:@selector(photoViewCameraTakePictureCompletion:model:)]) {
        [self.delegate photoViewCameraTakePictureCompletion:self model:model];
    }
    if ([self.delegate respondsToSelector:@selector(photoListViewControllerDidDone:allList:photos:videos:original:)]) {
        [self.delegate photoListViewControllerDidDone:self allList:self.manager.afterSelectedArray.copy photos:self.manager.afterSelectedPhotoArray.copy videos:self.manager.afterSelectedVideoArray.copy original:self.manager.afterOriginal];
    }
    [self setupDataWithAllList:self.manager.afterSelectedArray.copy photos:self.manager.afterSelectedPhotoArray.copy videos:self.manager.afterSelectedVideoArray.copy original:self.manager.afterOriginal];
}

- (void)deleteModelWithIndex:(NSInteger)index {
    if (index < 0) {
        index = 0;
    }
    if (index > self.manager.afterSelectedArray.count - 1) {
        index = self.manager.afterSelectedArray.count - 1;
    }
    UICollectionViewCell *cell = [self.collectionView cellForItemAtIndexPath:[NSIndexPath indexPathForItem:index inSection:0]];
    if (cell) {
        [self cellDidDeleteClcik:cell];
    }else {
        if (HXShowLog) NSSLog(@"删除失败 - cell为空");
    }
}
/**
 cell删除按钮的代理

 @param cell 被删的cell
 */
- (void)cellDidDeleteClcik:(UICollectionViewCell *)cell {
    if (!cell) {
        return;
    }
    [(HXPhotoSubViewCell *)cell imageView].image = nil;
    NSIndexPath *indexPath = [self.collectionView indexPathForCell:cell];
    HXPhotoModel *model = self.dataList[indexPath.item];
    model.photoEdit = nil;
    [self.manager afterSelectedListdeletePhotoModel:model];
    if ((model.type == HXPhotoModelMediaTypePhoto || model.type == HXPhotoModelMediaTypePhotoGif) || (model.type == HXPhotoModelMediaTypeCameraPhoto || model.type == HXPhotoModelMediaTypeLivePhoto)) {
        [self.photos removeObject:model];
    }else if (model.type == HXPhotoModelMediaTypeVideo || model.type == HXPhotoModelMediaTypeCameraVideo) {
        [self.videos removeObject:model];
    }

    UIView *mirrorView = [cell snapshotViewAfterScreenUpdates:NO];
    mirrorView.frame = cell.frame;
    [self.collectionView insertSubview:mirrorView atIndex:0];
    cell.hidden = YES;
    [UIView animateWithDuration:0.25 animations:^{
        mirrorView.transform = CGAffineTransformMakeScale(0.0001, 0.0001);
    } completion:^(BOOL finished) {
        cell.hidden = NO;
        HXPhotoSubViewCell *myCell = (HXPhotoSubViewCell *)cell;
        myCell.imageView.image = nil;
        [mirrorView removeFromSuperview];
    }];
    [self.dataList removeObjectAtIndex:indexPath.item];

    [self.collectionView performBatchUpdates:^{
        [self.collectionView deleteItemsAtIndexPaths:@[indexPath]];
    } completion:^(BOOL finished) {
        BOOL collectionReload = YES;
        if (self.showAddCell) {
            if (!self.tempShowAddCell) {
                self.tempShowAddCell = YES;
                [CATransaction begin];
                [CATransaction setDisableActions:YES];
                [self.collectionView reloadData];
                dispatch_async(dispatch_get_main_queue(), ^{
                    [CATransaction commit];
                });
                collectionReload = NO;
            }
        }
        if (self.cellCustomProtocol && collectionReload) {
            [CATransaction begin];
            [CATransaction setDisableActions:YES];
            [self.collectionView reloadData];
            dispatch_async(dispatch_get_main_queue(), ^{
                [CATransaction commit];
            });
        }
        [self setupNewFrame];
    }];
    [self changeSelectedListModelIndex];
    if (model.networkPhotoUrl) {
        if ([self.delegate respondsToSelector:@selector(photoView:deleteNetworkPhoto:)]) {
            [self.delegate photoView:self deleteNetworkPhoto:model.networkPhotoUrl.absoluteString];
        }
        if (self.deleteNetworkPhotoBlock) {
            self.deleteNetworkPhotoBlock(model.networkPhotoUrl.absoluteString);
        }
    }
    if ([self.delegate respondsToSelector:@selector(photoView:changeComplete:photos:videos:original:)]) {
        [self.delegate photoView:self changeComplete:self.dataList.copy photos:self.photos.copy videos:self.videos.copy original:self.original];
    }

    if ([self.delegate respondsToSelector:@selector(photoListViewControllerDidDone:allList:photos:videos:original:)]) {
        [self.delegate photoListViewControllerDidDone:self allList:self.manager.afterSelectedArray.copy photos:self.manager.afterSelectedPhotoArray.copy videos:self.manager.afterSelectedVideoArray.copy original:self.manager.afterOriginal];
    }
    if ([self.delegate respondsToSelector:@selector(photoViewChangeComplete:allAssetList:photoAssets:videoAssets:original:)]) {
        NSMutableArray *allAsset = [NSMutableArray array];
        NSMutableArray *photoAssets = [NSMutableArray array];
        NSMutableArray *videoAssets = [NSMutableArray array];
        for (HXPhotoModel *phMd in self.dataList) {
            if (phMd.asset) {
                if (phMd.subType == HXPhotoModelMediaSubTypePhoto) {
                    [photoAssets addObject:phMd.asset];
                }else {
                    [videoAssets addObject:phMd.asset];
                }
                [allAsset addObject:phMd.asset];
            }
        }
        [self.delegate photoViewChangeComplete:self allAssetList:allAsset photoAssets:photoAssets videoAssets:videoAssets original:self.original];
    }
    if (self.changeCompleteBlock) {
        self.changeCompleteBlock(self.dataList.copy, self.photos.copy, self.videos.copy, self.original);
    }
    if ([self.delegate respondsToSelector:@selector(photoView:currentDeleteModel:currentIndex:)]) {
        [self.delegate photoView:self currentDeleteModel:model currentIndex:indexPath.item];
    }
    if (self.currentDeleteModelBlock) {
        self.currentDeleteModelBlock(model, indexPath.item);
    }
    if (model.type != HXPhotoModelMediaTypeCameraPhoto &&
        model.type != HXPhotoModelMediaTypeCameraVideo) {
        model.thumbPhoto = nil;
        model.previewPhoto = nil;
        model = nil;
    }
}

- (void)changeSelectedListModelIndex {
    int i = 0;
    for (HXPhotoModel *model in self.dataList) {
        model.selectedIndex = i;
        model.selectIndexStr = [NSString stringWithFormat:@"%d",i + 1];
        i++;
    }
}
- (void)setupDataWithAllList:(NSArray *)allList photos:(NSArray *)photos videos:(NSArray *)videos original:(BOOL)original {

    self.original = original;
    NSMutableArray *tempAllArray = [NSMutableArray array];
    NSMutableArray *tempPhotoArray = [NSMutableArray array];
    [tempAllArray addObjectsFromArray:allList];
    [tempPhotoArray addObjectsFromArray:photos];
    allList = tempAllArray;
    photos = tempPhotoArray;

    self.photos = [NSMutableArray arrayWithArray:photos];
    self.videos = [NSMutableArray arrayWithArray:videos];
    [self.dataList removeAllObjects];
    [self.dataList addObjectsFromArray:allList];
    if (self.showAddCell) {
        self.tempShowAddCell = YES;
        if (self.manager.configuration.selectTogether) {
            if (self.manager.configuration.maxNum == allList.count) {
                self.tempShowAddCell = NO;
            }
        }else {
            if (photos.count > 0) {
                NSInteger maxCount = self.manager.configuration.photoMaxNum > 0 ? self.manager.configuration.photoMaxNum : self.manager.configuration.maxNum;
                if (photos.count == maxCount) {
                    if (maxCount > 0) {
                        self.tempShowAddCell = NO;
                    }
                }
            }else if (videos.count > 0) {
                NSInteger maxCount = self.manager.configuration.videoMaxNum > 0 ? self.manager.configuration.videoMaxNum : self.manager.configuration.maxNum;
                if (videos.count == maxCount) {
                    if (maxCount > 0) {
                        self.tempShowAddCell = NO;
                    }
                }
            }
        }
    }
    [self changeSelectedListModelIndex];
    [self.collectionView reloadData];
    if ([self.delegate respondsToSelector:@selector(photoView:changeComplete:photos:videos:original:)]) {
        [self.delegate photoView:self changeComplete:allList.copy photos:photos.copy videos:videos.copy original:original];
    }
    if ([self.delegate respondsToSelector:@selector(photoViewChangeComplete:allAssetList:photoAssets:videoAssets:original:)]) {
        NSMutableArray *allAsset = [NSMutableArray array];
        NSMutableArray *photoAssets = [NSMutableArray array];
        NSMutableArray *videoAssets = [NSMutableArray array];
        for (HXPhotoModel *phMd in allList) {
            if (phMd.asset) {
                if (phMd.subType == HXPhotoModelMediaSubTypePhoto) {
                    [photoAssets addObject:phMd.asset];
                }else {
                    [videoAssets addObject:phMd.asset];
                }
                [allAsset addObject:phMd.asset];
            }
        }
        [self.delegate photoViewChangeComplete:self allAssetList:allAsset photoAssets:photoAssets videoAssets:videoAssets original:original];
    }
    if (self.changeCompleteBlock) {
        self.changeCompleteBlock(allList.copy, photos.copy, videos.copy, original);
    }
    [self layoutSubviews];
    if (self.scrollDirection == UICollectionViewScrollDirectionHorizontal &&
        self.dataList.count) {
        NSInteger currentItem = self.tempShowAddCell ? self.dataList.count : self.dataList.count - 1;
        [self.collectionView scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:currentItem inSection:0] atScrollPosition:UICollectionViewScrollPositionRight animated:YES];
    }
}
- (NSArray *)dataSourceArrayOfCollectionView:(HXCollectionView *)collectionView {
    return self.dataList;
}
- (void)dragCellCollectionView:(HXCollectionView *)collectionView newDataArrayAfterMove:(NSArray *)newDataArray {
    self.dataList = [NSMutableArray arrayWithArray:newDataArray];
}
- (void)dragCellCollectionView:(HXCollectionView *)collectionView moveCellFromIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath {
    HXPhotoModel *fromModel = self.dataList[fromIndexPath.item];
    HXPhotoModel *toModel = self.dataList[toIndexPath.item];

    [self.manager afterSelectedArraySwapPlacesWithFromModel:fromModel fromIndex:fromIndexPath.item toModel:toModel toIndex:toIndexPath.item];

    [self.photos removeAllObjects];
    [self.videos removeAllObjects];
    NSInteger i = 0;
    for (HXPhotoModel *model in self.manager.afterSelectedArray) {
        model.selectIndexStr = [NSString stringWithFormat:@"%ld",i + 1];
        if (model.subType == HXPhotoModelMediaSubTypePhoto) {
            [self.photos addObject:model];
        }else if (model.subType == HXPhotoModelMediaSubTypeVideo) {
            [self.videos addObject:model];
        }
        i++;
    }
    [self.manager setAfterSelectedPhotoArray:self.photos];
    [self.manager setAfterSelectedVideoArray:self.videos];
}

- (void)dragCellCollectionViewCellEndMoving:(HXCollectionView *)collectionView {
    if ([self.delegate respondsToSelector:@selector(photoView:changeComplete:photos:videos:original:)]) {
        [self.delegate photoView:self changeComplete:self.dataList.copy photos:self.photos.copy videos:self.videos.copy original:self.original];
    }
    if ([self.delegate respondsToSelector:@selector(photoListViewControllerDidDone:allList:photos:videos:original:)]) {
        [self.delegate photoListViewControllerDidDone:self allList:self.manager.afterSelectedArray.copy photos:self.manager.afterSelectedPhotoArray.copy videos:self.manager.afterSelectedVideoArray.copy original:self.manager.afterOriginal];
    }
    if ([self.delegate respondsToSelector:@selector(photoViewChangeComplete:allAssetList:photoAssets:videoAssets:original:)]) {
        NSMutableArray *allAsset = [NSMutableArray array];
        NSMutableArray *photoAssets = [NSMutableArray array];
        NSMutableArray *videoAssets = [NSMutableArray array];
        for (HXPhotoModel *phMd in self.dataList) {
            if (phMd.asset) {
                if (phMd.subType == HXPhotoModelMediaSubTypePhoto) {
                    [photoAssets addObject:phMd.asset];
                }else {
                    [videoAssets addObject:phMd.asset];
                }
                [allAsset addObject:phMd.asset];
            }
        }
        [self.delegate photoViewChangeComplete:self allAssetList:allAsset photoAssets:photoAssets videoAssets:videoAssets original:self.original];
    }
    if (self.changeCompleteBlock) {
        self.changeCompleteBlock(self.dataList.copy, self.photos.copy, self.videos.copy, self.original);
    }
}
- (void)collectionViewNeedReloadData:(UICollectionView *)collectionView {
    if (self.cellCustomProtocol) {
        [self.collectionView reloadData];
    }
}
- (BOOL)collectionViewShouldDeleteCurrentMoveItem:(UICollectionView *)collectionView gestureRecognizer:(UILongPressGestureRecognizer *)longPgr indexPath:(NSIndexPath *)indexPath {
    if ([self.delegate respondsToSelector:@selector(photoViewShouldDeleteCurrentMoveItem:gestureRecognizer:indexPath:)]) {
        return [self.delegate photoViewShouldDeleteCurrentMoveItem:self gestureRecognizer:longPgr indexPath:indexPath];
    }
    if (self.shouldDeleteCurrentMoveItemBlock) {
        return self.shouldDeleteCurrentMoveItemBlock(longPgr, indexPath);
    }
    return NO;
}
- (void)collectionView:(UICollectionView *)collectionView gestureRecognizerBegan:(UILongPressGestureRecognizer *)longPgr indexPath:(NSIndexPath *)indexPath {
    if (indexPath) {
        if ([self.delegate respondsToSelector:@selector(photoView:gestureRecognizerBegan:indexPath:)]) {
            [self.delegate photoView:self gestureRecognizerBegan:longPgr indexPath:indexPath];
        }
        if (self.longGestureRecognizerBeganBlock) {
            self.longGestureRecognizerBeganBlock(longPgr, indexPath);
        }
    }
}
- (void)collectionView:(UICollectionView *)collectionView gestureRecognizerChange:(UILongPressGestureRecognizer *)longPgr indexPath:(NSIndexPath *)indexPath {
    if (indexPath) {
        HXPhotoSubViewCell *cell = (HXPhotoSubViewCell *)[self.collectionView cellForItemAtIndexPath:indexPath];
        if (cell.model.type == HXPhotoModelMediaTypeCamera) {
            return;
        }
        if ([self.delegate respondsToSelector:@selector(photoView:gestureRecognizerChange:indexPath:)]) {
            [self.delegate photoView:self gestureRecognizerChange:longPgr indexPath:indexPath];
        }
        if (self.longGestureRecognizerChangeBlock) {
            self.longGestureRecognizerChangeBlock(longPgr, indexPath);
        }
    }
}
- (void)collectionView:(UICollectionView *)collectionView gestureRecognizerEnded:(UILongPressGestureRecognizer *)longPgr indexPath:(NSIndexPath *)indexPath {
    if (indexPath) {
        if ([self.delegate respondsToSelector:@selector(photoView:gestureRecognizerEnded:indexPath:)]) {
            [self.delegate photoView:self gestureRecognizerEnded:longPgr indexPath:indexPath];
        }
        if (self.longGestureRecognizerEndedBlock) {
            self.longGestureRecognizerEndedBlock(longPgr, indexPath);
        }
    }
}

- (NSIndexPath *)currentModelIndexPath:(HXPhotoModel *)model {
    if ([self.dataList containsObject:model]) {
        return [NSIndexPath indexPathForItem:[self.dataList indexOfObject:model] inSection:0];
    }
    return [NSIndexPath indexPathForItem:0 inSection:0];
}
#pragma mark - < 更新高度 >
- (void)setupNewFrame {
    BOOL needUpdateFrame = NO;
    if (self.lastWidth) {
        if (self.lastWidth != self.hx_w) {
            needUpdateFrame = YES;
        }
    }
    UIEdgeInsets insets = self.collectionView.contentInset;
    CGFloat itemW = (NSInteger)((self.hx_w - self.spacing * (self.lineCount - 1) - insets.left - insets.right) / self.lineCount);
    if (self.scrollDirection == UICollectionViewScrollDirectionHorizontal &&
        itemW > 20) {
        itemW -= 10;
    }
    if (itemW <= 0) {
        itemW = 100;
    }
#if HXPhotoViewCustomItemSizeEnable
    itemW = 100;
#else
    if (!HXPhotoViewCustomItemSize) {
        self.flowLayout.itemSize = CGSizeMake(itemW, itemW);
    }else {
        itemW = 100;
    }
#endif

    NSInteger dataCount = self.tempShowAddCell ? self.dataList.count + 1 : self.dataList.count;
    NSInteger numOfLinesNew = 0;
    if (self.lineCount != 0) numOfLinesNew = (dataCount / self.lineCount) + 1;
    if (dataCount % self.lineCount == 0) numOfLinesNew -= 1;
    self.flowLayout.minimumLineSpacing = self.spacing;
    self.flowLayout.minimumInteritemSpacing = self.spacing;

    if (numOfLinesNew != self.numOfLinesOld || needUpdateFrame) {
        self.numOfLinesOld = numOfLinesNew;
        CGFloat newHeight;
        if ([self.delegate respondsToSelector:@selector(photoViewHeight:)] ||
            [self.delegate respondsToSelector:@selector(collectionView:layout:sizeForItemAtIndexPath:isAddItem:photoView:)]) {
            if (![self.delegate respondsToSelector:@selector(photoViewHeight:)]) {
                NSAssert(NO, @"请实现此代理 - (CGFloat)photoViewHeight:(HXPhotoView *)photoView");
            }
            newHeight = [self.delegate photoViewHeight:self];
            if (newHeight <= 0) {
                newHeight = 0;
                self.numOfLinesOld = 0;
            }
            self.hx_h = newHeight;
        }else {
            newHeight = numOfLinesNew * itemW + self.spacing * (numOfLinesNew - 1);
            if (newHeight <= 0) {
                newHeight = 0;
                self.numOfLinesOld = 0;
            }
            if (newHeight > self.maximumHeight) {
                newHeight = self.maximumHeight;
                _collectionView.scrollEnabled = YES;
            }else {
                if (self.scrollDirection != UICollectionViewScrollDirectionHorizontal) {
                    _collectionView.scrollEnabled = NO;
                }
            }
            if (self.scrollDirection == UICollectionViewScrollDirectionHorizontal) {
                self.hx_h = itemW;
            }else {
                self.hx_h = newHeight;
            }
        }
        if ([self.delegate respondsToSelector:@selector(photoView:updateFrame:)]) {
            [self.delegate photoView:self updateFrame:self.frame];
        }
        BOOL hasConstraints = self.constraints.count;
        if (hasConstraints) {
            self.collectionView.frame = self.bounds;
        }
        if (self.updateFrameBlock) {
            self.updateFrameBlock(self.frame);
        }
    }
    self.lastWidth = self.hx_w;
}

- (void)layoutSubviews {
    [super layoutSubviews];
    if (self.hx_w <= 0) {
        return;
    }
    if (self.lineCount <= 0) self.lineCount = 1;
    NSInteger dataCount = self.tempShowAddCell ? self.dataList.count + 1 : self.dataList.count;

    [self setupNewFrame];

    CGFloat width = self.frame.size.width;
    CGFloat height = self.frame.size.height;

    BOOL hasConstraints = self.constraints.count;

    if (dataCount == 1) {
        if ([self.delegate respondsToSelector:@selector(photoViewHeight:)] ||
                   [self.delegate respondsToSelector:@selector(collectionView:layout:sizeForItemAtIndexPath:isAddItem:photoView:)]) {
            if (![self.delegate respondsToSelector:@selector(photoViewHeight:)]) {
                NSAssert(NO, @"请实现此代理 - (CGFloat)photoViewHeight:(HXPhotoView *)photoView");
            }
            if (self.constraints.count) {
                NSAssert(NO, @"自定义HXPhotoView高度时,请不要使用约束布局");
            }
            CGFloat height = [self.delegate photoViewHeight:self];
            if (height != self.hx_h) {
                self.hx_h = height;
            }
        }else {
            UIEdgeInsets insets = self.collectionView.contentInset;
            CGFloat itemW = (width - self.spacing * (self.lineCount - 1) - insets.left - insets.right) / self.lineCount;
            CGFloat roundH = roundf(height);
            CGFloat roundW = roundf(itemW);
            if (roundH != roundW && fabs(height - itemW) >= 2) {
                if (itemW != self.hx_h && !hasConstraints) {
                    self.hx_h = itemW;
                }
            }
        }
    }
    if (!hasConstraints) {
        self.collectionView.frame = self.bounds;
        if (self.collectionView.hx_h <= 0) {
            self.numOfLinesOld = 0;
            [self setupNewFrame];
            self.collectionView.frame = self.bounds;
        }
    }
}
- (void)dealloc {
    if (HXShowLog) NSSLog(@"dealloc");
}

@end


text:
package org.apache.calcite.sql.hive;

/** Hive SQL parser. */
@SuppressWarnings("unused")
public class Hive {
  // This class is currently a place-holder to commit the src/main/java folder.
}

redpajama_set_name: RedPajamaGithub


text:
FROM mcr.microsoft.com/oryx/node:6.2-20190708.2
LABEL maintainer="Azure App Services Container Images <appsvc-images@microsoft.com>"

RUN echo "ipv6" >> /etc/modules

RUN npm install -g pm2 \
     && mkdir -p /home/LogFiles /opt/startup \
     && echo "root:Docker!" | chpasswd \
     && echo "cd /home" >> /etc/bash.bashrc \
     && apt-get update \
     && apt-get install --yes --no-install-recommends openssh-server vim curl wget tcptraceroute openrc

# setup default site
RUN rm -f /etc/ssh/sshd_config
COPY startup /opt/startup
COPY hostingstart.html /opt/startup

# configure startup
RUN mkdir -p /tmp
COPY sshd_config /etc/ssh/

COPY ssh_setup.sh /tmp
RUN chmod -R +x /opt/startup \
   && chmod -R +x /tmp/ssh_setup.sh \
   && (sleep 1;/tmp/ssh_setup.sh 2>&1 > /dev/null) \
   && rm -rf /tmp/* \
   && cd /opt/startup \
   && npm install

ENV PORT 8080
ENV SSH_PORT 2222
EXPOSE 2222 8080

ENV PM2HOME /pm2home

ENV WEBSITE_ROLE_INSTANCE_ID localRoleInstance
ENV WEBSITE_INSTANCE_ID localInstance
ENV PATH ${PATH}:/home/site/wwwroot

WORKDIR /home/site/wwwroot

ENTRYPOINT ["/opt/startup/init_container.sh"]


text:
from __future__ import unicode_literals

from django.db import migrations, models

class Migration(migrations.Migration):

    dependencies = [
        ('spanish_content', '0009_auto_20170304_1833'),
    ]

    operations = [
        migrations.AlterField(
            model_name='home',
            name='link',
            field=models.URLField(blank=True, help_text='Please enter a link for learn more button', null=True),
        ),
    ]


text:
namespace crashpad {
namespace test {
namespace {

#define TEST_STRING(process_reader, self_view, proctype_view, field)        \
  do {                                                                      \
    if (self_view->field) {                                                 \
      std::string proctype_string;                                          \
      ASSERT_TRUE(process_reader.Memory()->ReadCString(proctype_view.field, \
                                                       &proctype_string));  \
      EXPECT_EQ(self_view->field, proctype_string);                         \
    }                                                                       \
  } while (false)

TEST(ProcessTypes, DyldImagesSelf) {
  // Get the in-process view of dyld_all_image_infos, and check it for sanity.
  const struct dyld_all_image_infos* self_image_infos =
      _dyld_get_all_image_infos();
  int mac_os_x_minor_version = MacOSXMinorVersion();
  if (mac_os_x_minor_version >= 9) {
    EXPECT_GE(self_image_infos->version, 13u);
  } else if (mac_os_x_minor_version >= 7) {
    EXPECT_GE(self_image_infos->version, 8u);
  } else if (mac_os_x_minor_version >= 6) {
    EXPECT_GE(self_image_infos->version, 2u);
  } else {
    EXPECT_GE(self_image_infos->version, 1u);
  }

  EXPECT_GT(self_image_infos->infoArrayCount, 1u);
  if (self_image_infos->version >= 2) {
    EXPECT_TRUE(self_image_infos->libSystemInitialized);
  }
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
  if (self_image_infos->version >= 9) {
    EXPECT_EQ(self_image_infos, self_image_infos->dyldAllImageInfosAddress);
  }
#endif

  // Get the out-of-process view of dyld_all_image_infos, and work with it
  // through the process_types interface.
  task_dyld_info_data_t dyld_info;
  mach_msg_type_number_t count = TASK_DYLD_INFO_COUNT;
  kern_return_t kr = task_info(mach_task_self(),
                               TASK_DYLD_INFO,
                               reinterpret_cast<task_info_t>(&dyld_info),
                               &count);
  ASSERT_EQ(KERN_SUCCESS, kr);

  EXPECT_EQ(reinterpret_cast<mach_vm_address_t>(self_image_infos),
            dyld_info.all_image_info_addr);
  EXPECT_GT(dyld_info.all_image_info_size, 1u);

#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
#if !defined(ARCH_CPU_64_BITS)
  EXPECT_EQ(TASK_DYLD_ALL_IMAGE_INFO_32, dyld_info.all_image_info_format);
#else
  EXPECT_EQ(TASK_DYLD_ALL_IMAGE_INFO_64, dyld_info.all_image_info_format);
#endif
#endif

  ProcessReader process_reader;
  ASSERT_TRUE(process_reader.Initialize(mach_task_self()));

  process_types::dyld_all_image_infos proctype_image_infos;
  ASSERT_TRUE(proctype_image_infos.Read(&process_reader,
                                        dyld_info.all_image_info_addr));

  ASSERT_EQ(self_image_infos->version, proctype_image_infos.version);

  if (proctype_image_infos.version >= 1) {
    EXPECT_EQ(self_image_infos->infoArrayCount,
              proctype_image_infos.infoArrayCount);
    EXPECT_EQ(reinterpret_cast<uint64_t>(self_image_infos->infoArray),
              proctype_image_infos.infoArray);
    EXPECT_EQ(reinterpret_cast<uint64_t>(self_image_infos->notification),
              proctype_image_infos.notification);
    EXPECT_EQ(self_image_infos->processDetachedFromSharedRegion,
              proctype_image_infos.processDetachedFromSharedRegion);
  }
  if (proctype_image_infos.version >= 2) {
    EXPECT_EQ(self_image_infos->libSystemInitialized,
              proctype_image_infos.libSystemInitialized);
    EXPECT_EQ(
        reinterpret_cast<uint64_t>(self_image_infos->dyldImageLoadAddress),
        proctype_image_infos.dyldImageLoadAddress);
  }
  if (proctype_image_infos.version >= 3) {
    EXPECT_EQ(reinterpret_cast<uint64_t>(self_image_infos->jitInfo),
              proctype_image_infos.jitInfo);
  }
  if (proctype_image_infos.version >= 5) {
    EXPECT_EQ(reinterpret_cast<uint64_t>(self_image_infos->dyldVersion),
              proctype_image_infos.dyldVersion);
    EXPECT_EQ(reinterpret_cast<uint64_t>(self_image_infos->errorMessage),
              proctype_image_infos.errorMessage);
    EXPECT_EQ(static_cast<uint64_t>(self_image_infos->terminationFlags),
              proctype_image_infos.terminationFlags);

    TEST_STRING(
        process_reader, self_image_infos, proctype_image_infos, dyldVersion);
    TEST_STRING(
        process_reader, self_image_infos, proctype_image_infos, errorMessage);
  }
  if (proctype_image_infos.version >= 6) {
    EXPECT_EQ(
        reinterpret_cast<uint64_t>(self_image_infos->coreSymbolicationShmPage),
        proctype_image_infos.coreSymbolicationShmPage);
  }
  if (proctype_image_infos.version >= 7) {
    EXPECT_EQ(static_cast<uint64_t>(self_image_infos->systemOrderFlag),
              proctype_image_infos.systemOrderFlag);
  }
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
  if (proctype_image_infos.version >= 8) {
    EXPECT_EQ(static_cast<uint64_t>(self_image_infos->uuidArrayCount),
              proctype_image_infos.uuidArrayCount);
  }
  if (proctype_image_infos.version >= 9) {
    EXPECT_EQ(
        reinterpret_cast<uint64_t>(self_image_infos->dyldAllImageInfosAddress),
        proctype_image_infos.dyldAllImageInfosAddress);
  }
  if (proctype_image_infos.version >= 10) {
    EXPECT_EQ(static_cast<uint64_t>(self_image_infos->initialImageCount),
              proctype_image_infos.initialImageCount);
  }
  if (proctype_image_infos.version >= 11) {
    EXPECT_EQ(static_cast<uint64_t>(self_image_infos->errorKind),
              proctype_image_infos.errorKind);
    EXPECT_EQ(
        reinterpret_cast<uint64_t>(self_image_infos->errorClientOfDylibPath),
        proctype_image_infos.errorClientOfDylibPath);
    EXPECT_EQ(
        reinterpret_cast<uint64_t>(self_image_infos->errorTargetDylibPath),
        proctype_image_infos.errorTargetDylibPath);
    EXPECT_EQ(reinterpret_cast<uint64_t>(self_image_infos->errorSymbol),
              proctype_image_infos.errorSymbol);

    TEST_STRING(process_reader,
                self_image_infos,
                proctype_image_infos,
                errorClientOfDylibPath);
    TEST_STRING(process_reader,
                self_image_infos,
                proctype_image_infos,
                errorTargetDylibPath);
    TEST_STRING(
        process_reader, self_image_infos, proctype_image_infos, errorSymbol);
  }
  if (proctype_image_infos.version >= 12) {
    EXPECT_EQ(static_cast<uint64_t>(self_image_infos->sharedCacheSlide),
              proctype_image_infos.sharedCacheSlide);
  }
#endif
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9
  if (proctype_image_infos.version >= 13) {
    EXPECT_EQ(0,
              memcmp(self_image_infos->sharedCacheUUID,
                     proctype_image_infos.sharedCacheUUID,
                     sizeof(self_image_infos->sharedCacheUUID)));
  }
  if (proctype_image_infos.version >= 14) {
    for (size_t index = 0; index < arraysize(self_image_infos->reserved);
         ++index) {
      EXPECT_EQ(static_cast<uint64_t>(self_image_infos->reserved[index]),
                proctype_image_infos.reserved[index])
          << "index " << index;
    }
  }
#endif

  if (proctype_image_infos.version >= 1) {
    std::vector<process_types::dyld_image_info> proctype_image_info_vector(
        proctype_image_infos.infoArrayCount);
    ASSERT_TRUE(process_types::dyld_image_info::ReadArrayInto(
        &process_reader,
        proctype_image_infos.infoArray,
        proctype_image_info_vector.size(),
        &proctype_image_info_vector[0]));

    for (size_t index = 0; index < proctype_image_infos.infoArrayCount;
         ++index) {
      const dyld_image_info* self_image_info =
          &self_image_infos->infoArray[index];
      const process_types::dyld_image_info& proctype_image_info =
          proctype_image_info_vector[index];

      EXPECT_EQ(reinterpret_cast<uint64_t>(self_image_info->imageLoadAddress),
                proctype_image_info.imageLoadAddress)
          << "index " << index;
      EXPECT_EQ(reinterpret_cast<uint64_t>(self_image_info->imageFilePath),
                proctype_image_info.imageFilePath)
          << "index " << index;
      EXPECT_EQ(static_cast<uint64_t>(self_image_info->imageFileModDate),
                proctype_image_info.imageFileModDate)
          << "index " << index;

      TEST_STRING(
          process_reader, self_image_info, proctype_image_info, imageFilePath);
    }
  }

#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
  if (proctype_image_infos.version >= 8) {
    std::vector<process_types::dyld_uuid_info> proctype_uuid_info_vector(
        proctype_image_infos.uuidArrayCount);
    ASSERT_TRUE(process_types::dyld_uuid_info::ReadArrayInto(
        &process_reader,
        proctype_image_infos.uuidArray,
        proctype_uuid_info_vector.size(),
        &proctype_uuid_info_vector[0]));

    for (size_t index = 0; index < proctype_image_infos.uuidArrayCount;
         ++index) {
      const dyld_uuid_info* self_uuid_info =
          &self_image_infos->uuidArray[index];
      const process_types::dyld_uuid_info& proctype_uuid_info =
          proctype_uuid_info_vector[index];

      EXPECT_EQ(reinterpret_cast<uint64_t>(self_uuid_info->imageLoadAddress),
                proctype_uuid_info.imageLoadAddress)
          << "index " << index;
      EXPECT_EQ(0,
                memcmp(self_uuid_info->imageUUID,
                       proctype_uuid_info.imageUUID,
                       sizeof(self_uuid_info->imageUUID)))
          << "index " << index;
    }
  }
#endif
}

}  // namespace
}  // namespace test
}  // namespace crashpad


text:
namespace blink {
namespace test {

namespace {
using base::Feature;
using input_prediction::FilterType;
using input_prediction::PredictorType;
}  // namespace

class FilterFactoryTest : public testing::Test {
 public:
  FilterFactoryTest() {
    CreateNewFactory(blink::features::kFilteringScrollPrediction,
                     PredictorType::kScrollPredictorTypeKalman,
                     FilterType::kEmpty);
  }
  FilterFactoryTest(const FilterFactoryTest&) = delete;
  FilterFactoryTest& operator=(const FilterFactoryTest&) = delete;

  void GetFilterParams(const FilterType& filter_type,
                       const PredictorType& predictor_type,
                       FilterParams* filter_params) {
    factory_->GetFilterParams(filter_type, predictor_type, filter_params);
  }

  FilterType GetFilterTypeFromName(const std::string& filter_name) {
    return factory_->GetFilterTypeFromName(filter_name);
  }

  std::unique_ptr<ui::InputFilter> CreateFilter(
      const input_prediction::FilterType filter_type,
      const input_prediction::PredictorType predictor_type) {
    return factory_->CreateFilter(filter_type, predictor_type);
  }

  void CreateNewFactory(const base::Feature& feature,
                        const input_prediction::PredictorType predictor_type,
                        const input_prediction::FilterType filter_type) {
    factory_ =
        std::make_unique<FilterFactory>(feature, predictor_type, filter_type);
  }

 private:
  std::unique_ptr<FilterFactory> factory_;
};

// Check if the FilterType returned is correct
TEST_F(FilterFactoryTest, TestGetFilterType) {
  EXPECT_EQ(input_prediction::FilterType::kEmpty,
            GetFilterTypeFromName(::features::kFilterNameEmpty));

  EXPECT_EQ(input_prediction::FilterType::kOneEuro,
            GetFilterTypeFromName(::features::kFilterNameOneEuro));

  // Default type Empty
  EXPECT_EQ(input_prediction::FilterType::kEmpty, GetFilterTypeFromName(""));
}

TEST_F(FilterFactoryTest, TestCreateFilter) {
  EXPECT_STREQ(
      ::features::kFilterNameEmpty,
      CreateFilter(input_prediction::FilterType::kEmpty,
                   input_prediction::PredictorType::kScrollPredictorTypeEmpty)
          ->GetName());

  EXPECT_STREQ(
      ::features::kFilterNameOneEuro,
      CreateFilter(input_prediction::FilterType::kOneEuro,
                   input_prediction::PredictorType::kScrollPredictorTypeEmpty)
          ->GetName());
}

// Test there is no params available for OneEuro filter
TEST_F(FilterFactoryTest, TestOneEuroNoParams) {
  FilterParams filter_params;

  GetFilterParams(FilterType::kOneEuro,
                  PredictorType::kScrollPredictorTypeKalman, &filter_params);
  EXPECT_TRUE(filter_params.empty());
}

// Test we get the params sent via fieldtrials params
TEST_F(FilterFactoryTest, TestOneEuroParams) {
  FilterParams filter_params;

  base::test::ScopedFeatureList scoped_feature_list;
  base::FieldTrialParams field_trial_params;

  field_trial_params[ui::OneEuroFilter::kParamMincutoff] = "33";
  field_trial_params[ui::OneEuroFilter::kParamBeta] = "42";
  scoped_feature_list.Reset();
  scoped_feature_list.InitAndEnableFeatureWithParameters(
      blink::features::kFilteringScrollPrediction, field_trial_params);

  // Create a new factory to load fieldtrials params values
  CreateNewFactory(blink::features::kFilteringScrollPrediction,
                   PredictorType::kScrollPredictorTypeKalman,
                   FilterType::kOneEuro);

  GetFilterParams(FilterType::kOneEuro,
                  PredictorType::kScrollPredictorTypeKalman, &filter_params);

  EXPECT_EQ((int)filter_params.size(), 2);
  EXPECT_EQ(filter_params.find(ui::OneEuroFilter::kParamMincutoff)->second, 33);
  EXPECT_EQ(filter_params.find(ui::OneEuroFilter::kParamBeta)->second, 42);

  // fieldtrials params shouldn't be available for another predictor
  filter_params.clear();
  GetFilterParams(FilterType::kOneEuro, PredictorType::kScrollPredictorTypeLsq,
                  &filter_params);

  EXPECT_TRUE(filter_params.empty());
}

TEST_F(FilterFactoryTest, TestGetFilter) {
  EXPECT_STREQ(
      ::features::kFilterNameEmpty,
      CreateFilter(FilterType::kEmpty, PredictorType::kScrollPredictorTypeEmpty)
          ->GetName());

  EXPECT_STREQ(::features::kFilterNameOneEuro,
               CreateFilter(FilterType::kOneEuro,
                            PredictorType::kScrollPredictorTypeEmpty)
                   ->GetName());
}

}  // namespace test
}  // namespace blink


text:
var assert = require('assert');

var R = require('..');

describe('add', function() {
    it('adds together two numbers', function() {
        assert.strictEqual(R.add(3, 7), 10);
    });

    it('is automatically curried', function() {
        var incr = R.add(1);
        assert.strictEqual(incr(42), 43);
    });

    it('throws if given no arguments', function() {
        assert.throws(R.add, TypeError);
    });
});


text:
package pcal;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import org.junit.Test;

import tlc2.output.EC;

public class Either5Test extends PCalModelCheckerTestCase {

	public Either5Test() {
		super("Either5", "pcal", new String[] {"-wf", "-termination"});
	}

	@Test
	public void testSpec() {
		assertTrue(recorder.recordedWithStringValue(EC.TLC_INIT_GENERATED1, "1"));
		assertTrue(recorder.recordedWithStringValues(EC.TLC_CHECKING_TEMPORAL_PROPS, "complete", "7"));
		assertTrue(recorder.recorded(EC.TLC_FINISHED));
		assertFalse(recorder.recorded(EC.GENERAL));
		assertTrue(recorder.recordedWithStringValues(EC.TLC_STATS, "10", "7", "0"));
		assertTrue(recorder.recordedWithStringValue(EC.TLC_SEARCH_DEPTH, "3"));

		assertZeroUncovered();
	}
}


text:
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;

namespace Svetsoft.Nmea
{
    /// <summary>
    ///     Represents a sentence of the NMEA specification for GPS range residuals.
    /// </summary>
    public class GrsSentence : NmeaSentence, IUtcTimeSentence
    {
        private readonly List<Distance> _satelliteResiduals;

        /// <summary>
        ///     Creates a new instance of the <see cref="GrsSentence" /> class.
        /// </summary>
        /// <param name="sentence">The sentence to create the instance from.</param>
        public GrsSentence(string sentence)
            : base(sentence)
        {
            _satelliteResiduals = new List<Distance>();
            Parse();
        }

        /// <summary>
        ///     Returns the list of satellite residuals.
        /// </summary>
        public ReadOnlyCollection<Distance> SatelliteResiduals
        {
            get { return new ReadOnlyCollection<Distance>(_satelliteResiduals); }
        }

        /// <summary>
        ///     Returns the type of residual.
        /// </summary>
        public ResidualType ResidualType { get; internal set; }

        /// <summary>
        ///     Returns the time of day, expressed as the Coordinated Universal Time (UTC).
        /// </summary>
        public TimeSpan UtcTime { get; internal set; }

        /// <summary>
        ///     Parses the fields of this sentence to its <see cref="GrsSentence" /> equivalent.
        /// </summary>
        private void Parse()
        {
            UtcTime = GetUtcTime(0);
            ResidualType = GetResidualType(1);
            AddSatelliteResidualRange(GetDistances(2, 12, DistanceUnit.Meters));
        }

        /// <summary>
        ///     Adds <see cref="Distance" /> elements of the specified collection to the end of the list.
        /// </summary>
        /// <param name="collection">The collection whose <see cref="Distance" /> elements should be added to the end of the list.</param>
        internal void AddSatelliteResidualRange(IEnumerable<Distance> collection)
        {
            _satelliteResiduals.AddRange(collection);
        }
    }
}


text:
typedef void(^GetGroupInfoCompletion)(MTTGroupEntity* group);
@interface DDGroupModule : NSObject
+ (instancetype)instance;
@property(assign)NSInteger recentGroupCount;
@property(strong) NSMutableDictionary* allGroups;         //所有群列表,key:group id value:MTTGroupEntity
@property(strong) NSMutableDictionary* allFixedGroup;     //所有固定群列表
-(MTTGroupEntity*)getGroupByGId:(NSString*)gId;
-(void)addGroup:(MTTGroupEntity*)newGroup;
- (void)getGroupInfogroupID:(NSString*)groupID completion:(GetGroupInfoCompletion)completion;
-(NSArray*)getAllGroups;
@end


text:
<!DOCTYPE html>

        <meta charset="utf-8">

        <meta http-equiv="X-UA-Compatible" content="IE=edge">

        <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">

        <title>ProtoMode Web Editor</title>

        <link rel="stylesheet" href="/css/bootstrap.min.css">