/*
 * 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 "WXComponentManager.h"
#import "WXComponent.h"
#import "WXComponent_internal.h"
#import "WXComponent+DataBinding.h"
#import "WXComponentFactory.h"
#import "WXDefine.h"
#import "NSArray+Weex.h"
#import "WXSDKInstance.h"
#import "WXAssert.h"
#import "WXUtility.h"
#import "WXMonitor.h"
#import "WXScrollerProtocol.h"
#import "WXSDKManager.h"
#import "WXSDKError.h"
#import "WXInvocationConfig.h"
#import "WXHandlerFactory.h"
#import "WXValidateProtocol.h"
#import "WXPrerenderManager.h"
#import "WXSDKInstance_performance.h"
#import "WXRootView.h"
#import "WXComponent+Layout.h"
#import "WXCoreBridge.h"
#import "WXComponent_performance.h"
#import "WXAnalyzerCenter.h"
#import "WXDisplayLinkManager.h"
#import "WXDarkSchemeProtocol.h"

static NSThread *WXComponentThread;

/* Task scheduled on component thread and triggered every N display link ticks.
 If display link is stopped, the tasks are also suspended. */
@interface WXComponentThreadTickTask : NSObject

@property (nonatomic, assign) NSUInteger displayTickCount; // Triggered every N display link ticks
@property (nonatomic, copy) dispatch_block_t block;

@end

@implementation WXComponentThreadTickTask

+ (instancetype)taskWithBlock:(dispatch_block_t)block tickCount:(NSUInteger)tickCount
{
    WXComponentThreadTickTask* task = [[WXComponentThreadTickTask alloc] init];
    task.displayTickCount = tickCount;
    task.block = block;
    return task;
}

@end

#define WXAssertComponentExist(component)  WXAssert(component, @"component not exists")
#define MAX_DROP_FRAME_FOR_BATCH   200

@interface WXComponentManager () <WXDisplayLinkClient>
@end

@implementation WXComponentManager
{
    __weak WXSDKInstance *_weexInstance;
    BOOL _isValid;
    
    BOOL _stopRunning;
    NSUInteger _noTaskTickCount;
    
    // access only on component thread
    NSMapTable<NSString *, WXComponent *> *_indexDict;
    NSMutableArray<dispatch_block_t> *_uiTaskQueue;
    NSMutableDictionary *_uiPrerenderTaskQueue;
    
    NSUInteger _displayTick;
    NSMutableArray<WXComponentThreadTickTask*> *_displayTaskQueue;
    
    // vdom depth and component count statistics
    NSUInteger _maxVdomDepth;
    NSUInteger _maxVdomDepthReported;
    NSUInteger _maxComponentCount;
    NSUInteger _maxComponentCountReported;

    WXComponent *_rootComponent;
    NSMutableArray *_fixedComponents;

    pthread_mutex_t _propertyMutex;
    pthread_mutexattr_t _propertMutexAttr;
    NSUInteger _syncUITaskCount;
}

+ (instancetype)sharedManager
{
    static id _sharedInstance = nil;
    static dispatch_once_t oncePredicate;
    dispatch_once(&oncePredicate, ^{
        _sharedInstance = [[self alloc] init];
    });
    return _sharedInstance;
}

- (instancetype)initWithWeexInstance:(id)weexInstance
{
    if (self = [self init]) {
        _weexInstance = weexInstance;
        _syncUITaskCount = 0;
        _indexDict = [NSMapTable strongToWeakObjectsMapTable];
        _fixedComponents = [NSMutableArray wx_mutableArrayUsingWeakReferences];
        _uiTaskQueue = [NSMutableArray array];
        _displayTaskQueue = [NSMutableArray array];
        _isValid = YES;
        pthread_mutexattr_init(&_propertMutexAttr);
        pthread_mutexattr_settype(&_propertMutexAttr, PTHREAD_MUTEX_RECURSIVE);
        pthread_mutex_init(&_propertyMutex, &_propertMutexAttr);
        
        WXPerformBlockOnComponentThread(^{
            // We should ensure that [WXDisplayLinkManager sharedInstance] is only invoked in component thread.
            [self _addVdomAndComponentCountTask];
            [self _startDisplayLink];
        });
    }
    
    return self;
}

- (instancetype)init
{
    if (self == [super init]) {
        _suspend = NO;
    }
    return self;
}

- (void)dealloc
{
    [NSMutableArray wx_releaseArray:_fixedComponents];
    pthread_mutex_destroy(&_propertyMutex);
    pthread_mutexattr_destroy(&_propertMutexAttr);
}

#pragma mark Thread Management

+ (NSThread *)componentThread
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        WXComponentThread = [[NSThread alloc] initWithTarget:[self sharedManager] selector:@selector(_runLoopThread) object:nil];
        [WXComponentThread setName:WX_COMPONENT_THREAD_NAME];
        [WXComponentThread setQualityOfService:[[NSThread mainThread] qualityOfService]];
        [WXComponentThread start];
    });
    
    return WXComponentThread;
}

- (void)_runLoopThread
{
    [[NSRunLoop currentRunLoop] addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode];
    
    while (!_stopRunning) {
        @autoreleasepool {
            [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
        }
    }
}

+ (void)_performBlockOnComponentThread:(void (^)(void))block
{
    if([NSThread currentThread] == [self componentThread]){
        block();
    } else {
        [self performSelector:@selector(_performBlockOnComponentThread:)
                     onThread:WXComponentThread
                   withObject:[block copy]
                waitUntilDone:NO];
    }
}

+ (void)_performBlockSyncOnComponentThread:(void (^)(void))block
{
    if([NSThread currentThread] == [self componentThread]){
        block();
    } else {
        [self performSelector:@selector(_performBlockOnComponentThread:)
                     onThread:WXComponentThread
                   withObject:[block copy]
                waitUntilDone:YES];
    }
}

- (void)startComponentTasks
{
    [self _awakeDisplayLink];
}

- (void)rootViewFrameDidChange:(CGRect)frame
{
    WXAssertComponentThread();
    CGSize size = _weexInstance.frame.size;
    [WXCoreBridge setDefaultDimensionIntoRoot:_weexInstance.instanceId
                                        width:size.width height:size.height
                           isWidthWrapContent:size.width == 0.0f isHeightWrapContent:size.height == 0.0f];
    [_rootComponent setNeedsLayout];
    [self startComponentTasks];
}

- (void)_addUITask:(void (^)(void))block
{
    if(!_uiPrerenderTaskQueue){
        _uiPrerenderTaskQueue = [NSMutableDictionary new];
    }
    if(self.weexInstance.needPrerender){
        NSMutableArray<dispatch_block_t> *tasks  = [_uiPrerenderTaskQueue objectForKey:[WXPrerenderManager getTaskKeyFromUrl:self.weexInstance.scriptURL.absoluteString]];
        if(!tasks){
            tasks = [NSMutableArray new];
        }
        [tasks addObject:block];
        [_uiPrerenderTaskQueue setObject:tasks forKey:[WXPrerenderManager getTaskKeyFromUrl:self.weexInstance.scriptURL.absoluteString]];
    }else{
        [_uiTaskQueue addObject:block];
    }
}

- (void)executePrerenderUITask:(NSString *)url
{
    NSMutableArray *tasks  = [_uiPrerenderTaskQueue objectForKey:[WXPrerenderManager getTaskKeyFromUrl:self.weexInstance.scriptURL.absoluteString]];
    for (id block in tasks) {
        [_uiTaskQueue addObject:block];
    }
    tasks = [NSMutableArray new];
    [_uiPrerenderTaskQueue setObject:tasks forKey:[WXPrerenderManager getTaskKeyFromUrl:self.weexInstance.scriptURL.absoluteString]];
}

#pragma mark Component Tree Building

- (void)createBody:(NSString*)ref
              type:(NSString*)type
            styles:(NSDictionary*)styles
        attributes:(NSDictionary*)attributes
            events:(NSArray*)events
      renderObject:(void*)renderObject
{
    WXAssertComponentThread();
    WXAssertParam(ref);
    WXAssertParam(type);
    WXAssertParam(renderObject);
    WXAssert(_rootComponent == nil, @"Create body is invoked twice.");
    
    _rootComponent = [self _buildComponent:ref type:type supercomponent:nil styles:styles attributes:attributes events:events renderObject:renderObject];
    
    if ([WXUtility isDarkSchemeSupportEnabled]) {
        if (attributes[@"invertForDarkScheme"] == nil) {
            _rootComponent.invertForDarkScheme = [[WXSDKInstance darkSchemeColorHandler] defaultInvertValueForRootComponent];
        }
    }
    
    CGSize size = _weexInstance.frame.size;
    [WXCoreBridge setDefaultDimensionIntoRoot:_weexInstance.instanceId
                                        width:size.width height:size.height
                           isWidthWrapContent:size.width == 0.0f isHeightWrapContent:size.height == 0.0f];
    
    __weak typeof(self) weakSelf = self;
    WX_MONITOR_INSTANCE_PERF_END(WXFirstScreenJSFExecuteTime, self.weexInstance);
    [self _addUITask:^{
        __strong typeof(self) strongSelf = weakSelf;
        if (strongSelf == nil) {
            return;
        }
        
        strongSelf.weexInstance.rootView.wx_component = strongSelf->_rootComponent;
        [strongSelf.weexInstance.rootView addSubview:strongSelf->_rootComponent.view];
    }];
}

- (void)addComponent:(NSString*)ref
                type:(NSString*)type
           parentRef:(NSString*)parentRef
              styles:(NSDictionary*)styles
          attributes:(NSDictionary*)attributes
              events:(NSArray*)events
               index:(NSInteger)index
        renderObject:(void*)renderObject
{
    WXAssertComponentThread();
    WXAssertParam(ref);
    WXAssertParam(type);
    WXAssertParam(parentRef);
    WXAssertParam(renderObject);
    
    WXComponent *supercomponent = [_indexDict objectForKey:parentRef];
    WXAssertComponentExist(supercomponent);
    
    if (!supercomponent) {
        WXLogWarning(@"addComponent,superRef from js never exit ! check JS action, supRef:%@", parentRef);
        return;
    }
    if([WXAnalyzerCenter isInteractionLogOpen]){
         WXLogDebug(@"wxInteractionAnalyzer: [client][addElementStart]%@,%@,%@",supercomponent.weexInstance.instanceId,type,ref);
    }
    
    supercomponent.weexInstance.apmInstance.hasAddView = YES;
    
    WXComponent *component = [self _buildComponent:ref type:type supercomponent:supercomponent styles:styles attributes:attributes events:events renderObject:renderObject];
    if (!supercomponent.subcomponents) {
        index = 0;
    } else {
        index = (index == -1 ? supercomponent->_subcomponents.count : index);
    }
    if (supercomponent.ignoreInteraction) {
        component.ignoreInteraction = YES;
    } else {
        if ([attributes objectForKey:@"ignoreInteraction"]) {
            component.ignoreInteraction = [[attributes objectForKey:@"ignoreInteraction"] boolValue];
        } else {
            if (component->_positionType == WXPositionTypeFixed) {
                component.ignoreInteraction = YES;
            } else {
                component.ignoreInteraction = NO;
            }
        }
    }
    
    // Not explicitly declare "invertForDarkScheme", inherit
    if (attributes[@"invertForDarkScheme"] == nil) {
        component.invertForDarkScheme = supercomponent.invertForDarkScheme;
    }
    
#ifdef DEBUG
    WXLogDebug(@"flexLayout -> _recursivelyAddComponent : super:(%@,%@):[%f,%f] ,child:(%@,%@):[%f,%f],childClass:%@",
               supercomponent.type,
               supercomponent.ref,
               supercomponent.flexCssNode->getStyleWidth(),
               supercomponent.flexCssNode->getStyleHeight(),
               component.type,
               component.ref,
               component.flexCssNode->getStyleWidth(),
               component.flexCssNode->getStyleHeight(),
               NSStringFromClass([component class])
               );
#endif //DEBUG
    
    BOOL inserted = [supercomponent _insertSubcomponent:component atIndex:index];
    if (!inserted) {
        // component is not inserted, ignore
        [component _setRenderObject:nullptr]; // unbind with RenderObject
        return;
    }
    
    // use _lazyCreateView to forbid component like cell's view creating
    if (supercomponent && component && supercomponent->_lazyCreateView) {
        component->_lazyCreateView = YES;
    }
    
    // update max vdom depth & component count, and will update apm data on next display task.
    [self recordMaximumVirtualDom:component];
    if ([_indexDict count] > _maxComponentCount) {
        _maxComponentCount = [_indexDict count];
    }
    
    if (!component->_isTemplate) {
        __weak typeof(self) weakSelf = self;
        [self _addUITask:^{
            __strong typeof(self) strongSelf = weakSelf;
            if (strongSelf == nil) {
                return;
            }
            
            [supercomponent insertSubview:component atIndex:index];
        }];
    }
    if([WXAnalyzerCenter isInteractionLogOpen]){
        WXLogDebug(@"wxInteractionAnalyzer: [client][addElementEnd]%@,%@,%@",supercomponent.weexInstance.instanceId,type,ref);
    }
}

- (void)moveComponent:(NSString *)ref toSuper:(NSString *)superRef atIndex:(NSInteger)index
{
    WXAssertComponentThread();
    WXAssertParam(ref);
    WXAssertParam(superRef);
    
    WXComponent *component = [_indexDict objectForKey:ref];
    WXComponent *newSupercomponent = [_indexDict objectForKey:superRef];
    WXAssertComponentExist(component);
    WXAssertComponentExist(newSupercomponent);
    
    [component _moveToSupercomponent:newSupercomponent atIndex:index];
    __weak typeof(self) weakSelf = self;
    [self _addUITask:^{
        __strong typeof(self) strongSelf = weakSelf;
        if (strongSelf == nil) {
            return;
        }
        
        [component moveToSuperview:newSupercomponent atIndex:index];
    }];
}

- (void)removeComponent:(NSString *)ref
{
    WXAssertComponentThread();
    WXAssertParam(ref);
    
    WXComponent *component = [_indexDict objectForKey:ref];
    WXAssertComponentExist(component);
    
    if (!component) {
        WXLogWarning(@"removeComponent ref from js never exit ! check JS action, ref :%@",ref);
        return;
    }
    
    [component _setRenderObject:nullptr]; // unbind with RenderObject
    [component _removeFromSupercomponent];
    
    [_indexDict removeObjectForKey:ref];
    
    // remove subcomponents of component from _indexDict and unbind them
    NSMutableArray* subcomponents = [[NSMutableArray alloc] init];
    [component _collectSubcomponents:subcomponents];
    for (WXComponent* c in subcomponents) {
        [c _setRenderObject:nullptr];
        [_indexDict removeObjectForKey:c.ref];
    }
    
    __weak typeof(self) weakSelf = self;
    [self _addUITask:^{
        __strong typeof(self) strongSelf = weakSelf;
        if (strongSelf == nil) {
            return;
        }
        
        if (component.supercomponent) {
            [component.supercomponent willRemoveSubview:component];
        }
        [component removeFromSuperview];
    }];
    
    [self _checkFixedSubcomponentToRemove:component];
}

- (void)appendTreeCreateFinish:(NSString*)ref
{
    WXAssertComponentThread();
    
    // If appending tree，force layout in case of too much tasks piling up in syncQueue
    [self _layoutAndSyncUI];
}

- (void)recordMaximumVirtualDom:(WXComponent*) component
{
    WXAssertComponentExist(component);
    if(!component){
        return;
    }
    int maxDeep =0;
    while (component) {
        maxDeep++;
        component = component.supercomponent;
    }
    
    if (maxDeep > [self weexInstance].performance.maxVdomDeep) {
        [self weexInstance].performance.maxVdomDeep = maxDeep;
    }
    
    if (maxDeep > _maxVdomDepth) {
        _maxVdomDepth = maxDeep;
    }
}

- (void)_checkFixedSubcomponentToRemove:(WXComponent *)component
{
    for (WXComponent *subcomponent in component.subcomponents) {
        if (subcomponent->_positionType == WXPositionTypeFixed) {
             [self _addUITask:^{
                 [subcomponent removeFromSuperview];
             }];
        }
        
        [self _checkFixedSubcomponentToRemove:subcomponent];
    }
}

- (WXComponent *)componentForRef:(NSString *)ref
{
    WXAssertComponentThread();
    
    return [_indexDict objectForKey:ref];
}

- (WXComponent *)componentForRoot
{
    return _rootComponent;
}

- (NSUInteger)numberOfComponents
{
    WXAssertComponentThread();
    
    return _indexDict.count;
}

- (WXComponent *)_buildComponent:(NSString *)ref
                            type:(NSString*)type
                  supercomponent:(WXComponent *)supercomponent
                          styles:(NSDictionary*)styles
                      attributes:(NSDictionary*)attributes
                          events:(NSArray*)events
                    renderObject:(void*)renderObject
{
    double buildStartTime = CACurrentMediaTime()*1000;
    
    if (self.weexInstance.needValidate) {
        id<WXValidateProtocol> validateHandler = [WXHandlerFactory handlerForProtocol:@protocol(WXValidateProtocol)];
        if (validateHandler) {
            WXComponentValidateResult* validateResult;
            if ([validateHandler respondsToSelector:@selector(validateWithWXSDKInstance:component:supercomponent:)]) {
                validateResult = [validateHandler validateWithWXSDKInstance:self.weexInstance component:type supercomponent:supercomponent];
            }
            if (validateResult==nil || !validateResult.isSuccess) {
                type = validateResult.replacedComponent? validateResult.replacedComponent : @"div";
                WXLogError(@"%@",[validateResult.error.userInfo objectForKey:@"errorMsg"]);
            }
        }
    }
    
    WXComponentConfig *config = [WXComponentFactory configWithComponentName:type];
    BOOL isTemplate = [config.properties[@"isTemplate"] boolValue] || (supercomponent && supercomponent->_isTemplate);
    NSDictionary *bindingStyles = nil;
    NSDictionary *bindingAttibutes = nil;
    NSDictionary *bindingEvents = nil;
    NSDictionary *bindingProps = nil;
    if (isTemplate) {
        bindingProps = [self _extractBindingProps:&attributes];
        bindingStyles = [self _extractBindings:&styles];
        bindingAttibutes = [self _extractBindings:&attributes];
        bindingEvents = [self _extractBindingEvents:&events];
    }
    
    Class clazz = NSClassFromString(config.clazz);
    WXComponent *component = [[clazz alloc] init];
    if (component) {
        if (renderObject) {
            [component _setRenderObject:renderObject];
        }
        component = [component initWithRef:ref type:type styles:styles attributes:attributes events:events weexInstance:self.weexInstance];
        if (isTemplate) {
            component->_isTemplate = YES;
            [component _storeBindingsWithProps:bindingProps styles:bindingStyles attributes:bindingAttibutes events:bindingEvents];
        }
    }
    
    WXAssert(component, @"Component build failed for ref:%@, type:%@", ref, type);
    
    [_indexDict setObject:component forKey:component.ref];
    [component readyToRender];// notify redyToRender event when init
    
    double diffTime = CACurrentMediaTime()*1000 - buildStartTime;
    [self.weexInstance.performance recordComponentCreatePerformance:diffTime forComponent:component];
    
    return component;
}

- (void)addComponent:(WXComponent *)component toIndexDictForRef:(NSString *)ref
{
    [_indexDict setObject:component forKey:ref];
}

- (void)removeComponentForRef:(NSString *)ref
{
    [_indexDict removeObjectForKey:ref];
}

- (NSDictionary *)_extractBindings:(NSDictionary **)attributesOrStylesPoint
{
    NSDictionary *attributesOrStyles = *attributesOrStylesPoint;
    if (!attributesOrStyles) {
        return nil;
    }
    
    NSMutableDictionary *newAttributesOrStyles = [attributesOrStyles mutableCopy];
    NSMutableDictionary *bindingAttributesOrStyles = [NSMutableDictionary dictionary];
    
    [attributesOrStyles enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull attributeOrStyleName, id  _Nonnull attributeOrStyle, BOOL * _Nonnull stop) {
        if ([WXBindingMatchIdentify isEqualToString:attributeOrStyleName] // match
            ||  [WXBindingRepeatIdentify isEqualToString:attributeOrStyleName] // repeat
            ||  [WXBindingOnceIdentify isEqualToString:attributeOrStyleName] // once
            ||([attributeOrStyle isKindOfClass:[NSDictionary class]] && attributeOrStyle[WXBindingIdentify])) {  // {"attributeOrStyleName": {"@binding":"bindingExpression"}
            bindingAttributesOrStyles[attributeOrStyleName] = attributeOrStyle;
            [newAttributesOrStyles removeObjectForKey:attributeOrStyleName];
        } else if ([attributeOrStyle isKindOfClass:[NSArray class]]) {
            // {"attributeOrStyleName":[..., "string", {"@binding":"bindingExpression"}, "string", {"@binding":"bindingExpression"}, ...]
            __block BOOL isBinding = NO;
            [attributeOrStyle enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
                if ([obj isKindOfClass:[NSDictionary class]] && obj[WXBindingIdentify]) {
                    isBinding = YES;
                    *stop = YES;
                }
            }];
            
            if (isBinding) {
                bindingAttributesOrStyles[attributeOrStyleName] = attributeOrStyle;
                [newAttributesOrStyles removeObjectForKey:attributeOrStyleName];
            }
        }
    }];
    
    *attributesOrStylesPoint = newAttributesOrStyles;
    
    return bindingAttributesOrStyles;
}

- (NSDictionary *)_extractBindingEvents:(NSArray **)eventsPoint
{
    NSArray *events = *eventsPoint;
    if (events == nil) {
        return nil;
    }
    NSMutableArray *newEvents = [events mutableCopy];
    NSMutableDictionary *bindingEvents = [NSMutableDictionary dictionary];
    [events enumerateObjectsUsingBlock:^(id  _Nonnull event, NSUInteger idx, BOOL * _Nonnull stop) {
        if ([event isKindOfClass:[NSDictionary class]] && event[@"type"] && event[@"params"]) {
            NSString *eventName = event[@"type"];
            NSString *bindingParams = event[@"params"];
            bindingEvents[eventName] = bindingParams;
            newEvents[idx] = eventName;
        }
    }];
    
    *eventsPoint = newEvents;
    return bindingEvents;
}

- (NSDictionary *)_extractBindingProps:(NSDictionary **)attributesPoint
{
    NSDictionary *attributes = *attributesPoint;
    if (attributes == nil) {
        return nil;
    }
    if (attributes[@"@componentProps"]) {
        NSMutableDictionary *newAttributes = [attributes mutableCopy];
        [newAttributes removeObjectForKey:@"@componentProps"];
        *attributesPoint = newAttributes;
        return attributes[@"@componentProps"];
    }
    
    return nil;
}

#pragma mark Reset

- (BOOL)isShouldReset:(id )value
{
    if([value isKindOfClass:[NSString class]]) {
        if(!value || [@"" isEqualToString:value]) {
            return YES;
        }
    }
    return NO;
}

- (void)filterStyles:(NSDictionary *)styles normalStyles:(NSMutableDictionary *)normalStyles resetStyles:(NSMutableArray *)resetStyles
{
    for (NSString *key in styles) {
        id value = [styles objectForKey:key];
        if([self isShouldReset:value]) {
            [resetStyles addObject:key];
        }else{
            [normalStyles setObject:styles[key] forKey:key];
        }
    }
}

- (void)updateStyles:(NSDictionary *)styles forComponent:(NSString *)ref
{
    [self handleStyles:styles forComponent:ref isUpdateStyles:YES];
}

- (void)updatePseudoClassStyles:(NSDictionary *)styles forComponent:(NSString *)ref
{
    [self handleStyles:styles forComponent:ref isUpdateStyles:NO];
}

- (void)handleStyleOnMainThread:(NSDictionary*)styles forComponent:(WXComponent *)component isUpdateStyles:(BOOL)isUpdateStyles
{
    WXAssertParam(styles);
    WXAssertParam(component);
    WXAssertMainThread();
    
    NSMutableDictionary *normalStyles = [NSMutableDictionary new];
    NSMutableArray *resetStyles = [NSMutableArray new];
    [self filterStyles:styles normalStyles:normalStyles resetStyles:resetStyles];
    [component _updateStylesOnMainThread:normalStyles resetStyles:resetStyles];
    [component readyToRender];
    
    NSDictionary* dupStyles = [NSDictionary dictionaryWithDictionary:normalStyles];
    WXPerformBlockOnComponentThread(^{
        [component _updateStylesOnComponentThread:dupStyles resetStyles:resetStyles isUpdateStyles:isUpdateStyles];
    });
}

- (void)handleStyles:(NSDictionary *)styles forComponent:(NSString *)ref isUpdateStyles:(BOOL)isUpdateStyles
{
    WXAssertParam(styles);
    WXAssertParam(ref);
    
    WXComponent *component = [_indexDict objectForKey:ref];
    WXAssertComponentExist(component);
    
    NSMutableDictionary *normalStyles = [NSMutableDictionary new];
    NSMutableArray *resetStyles = [NSMutableArray new];
    [self filterStyles:styles normalStyles:normalStyles resetStyles:resetStyles];
    [component _updateStylesOnComponentThread:normalStyles resetStyles:resetStyles isUpdateStyles:isUpdateStyles];
    
    NSDictionary* dupStyles = [NSDictionary dictionaryWithDictionary:normalStyles];
    [self _addUITask:^{
        [component _updateStylesOnMainThread:dupStyles resetStyles:resetStyles];
        [component readyToRender];
    }];
}

- (void)updateAttributes:(NSDictionary *)attributes forComponent:(NSString *)ref
{
    WXAssertParam(attributes);
    WXAssertParam(ref);
    
    WXComponent *component = [_indexDict objectForKey:ref];
    [component _updateAttributesOnComponentThread:attributes];
    __weak typeof(self) weakSelf = self;
    [self _addUITask:^{
        __strong typeof(self) strongSelf = weakSelf;
        if (strongSelf == nil) {
            return;
        }
        
        [component _updateAttributesOnMainThread:attributes];
        [component readyToRender];
    }];
}

- (BOOL)isTransitionNoneOfComponent:(NSString*)ref
{
    WXAssertComponentThread();
    
    WXComponent *component = [_indexDict objectForKey:ref];
    WXAssertComponentExist(component);
    
    return [component _isTransitionNone];
}

- (BOOL)hasTransitionPropertyInStyles:(NSDictionary*)styles forComponent:(NSString*)ref
{
    WXAssertComponentThread();
    
    WXComponent *component = [_indexDict objectForKey:ref];
    WXAssertComponentExist(component);
    
    return [component _hasTransitionPropertyInStyles:styles];
}

- (void)layoutComponent:(WXComponent*)component frame:(CGRect)frame isRTL:(BOOL)isRTL innerMainSize:(CGFloat)innerMainSize
{
    WXAssertComponentThread();
    WXAssertParam(component);
    
    [component _setIsLayoutRTL:isRTL];
    if (component == _rootComponent) {
        // Synchronize view frame with root component, especially for content wrap mode.
        WXPerformBlockOnMainThread(^{
            if (!self.weexInstance.isRootViewFrozen &&
                (!CGSizeEqualToSize(frame.size, self.weexInstance.frame.size) || !CGSizeEqualToSize(frame.size, self.weexInstance.rootView.frame.size))) {
                CGRect rect = self.weexInstance.rootView.frame; // no change of origin
                rect.size = frame.size;
                self.weexInstance.rootView.frame = rect;
            }
        });
    }
    
    if ([component _isCalculatedFrameChanged:frame]) {
        [component _assignCalculatedFrame:frame];
        [component _assignInnerContentMainSize:innerMainSize];
        [component _frameDidCalculated:YES];
        
        [self _addUITask:^{
            [component _layoutDidFinish];
        }];
    }
    else {
        CGFloat oldValue = [component _getInnerContentMainSize];
        if (oldValue >= 0 && oldValue != innerMainSize) {
            [component _assignCalculatedFrame:frame];
            [component _assignInnerContentMainSize:innerMainSize];
            [component _frameDidCalculated:YES];
            
            [self _addUITask:^{
                [component _layoutDidFinish];
            }];
        }
        else {
            [component _frameDidCalculated:NO];
        }
    }
}

- (void)layoutComponent:(WXComponent*)component
{
    WXAssertComponentThread();
    WXAssertParam(component);
    [component _layoutPlatform];
}

- (void)addEvent:(NSString *)event toComponent:(NSString *)ref
{
    WXAssertComponentThread();
    WXAssertParam(event);
    WXAssertParam(ref);
    
    WXComponent *component = [_indexDict objectForKey:ref];
    WXAssertComponentExist(component);
    
    [component _addEventOnComponentThread:event];
    
    [self _addUITask:^{
        [component _addEventOnMainThread:event];
    }];
}

- (void)removeEvent:(NSString *)event fromComponent:(NSString *)ref
{
    WXAssertComponentThread();
    WXAssertParam(event);
    WXAssertParam(ref);
    
    WXComponent *component = [_indexDict objectForKey:ref];
    WXAssertComponentExist(component);
    
    [component _removeEventOnComponentThread:event];
    
    [self _addUITask:^{
        [component _removeEventOnMainThread:event];
    }];
}

- (void)scrollToComponent:(NSString *)ref options:(NSDictionary *)options
{
    WXAssertComponentThread();
    WXAssertParam(ref);
    
    WXComponent *toComponent = [_indexDict objectForKey:ref];
    WXAssertComponentExist(toComponent);

    id<WXScrollerProtocol> scrollerComponent = toComponent.ancestorScroller;
    if (!scrollerComponent) {
        return;
    }

    CGFloat offset = [[options objectForKey:@"offset"] floatValue];
    BOOL animated = YES;
    if ([options objectForKey:@"animated"]) {
        animated = [[options objectForKey:@"animated"] boolValue];
    }
    
    [self _addUITask:^{
        [scrollerComponent scrollToComponent:toComponent withOffset:offset animated:animated];
    }];
}

#pragma mark Life Cycle

- (void)createFinish
{
    WXAssertComponentThread();
    
    WXSDKInstance *instance  = self.weexInstance;
    [self _addUITask:^{
        
        WX_MONITOR_INSTANCE_PERF_END(WXPTFirstScreenRender, instance);
        WX_MONITOR_INSTANCE_PERF_END(WXPTAllRender, instance);
        WX_MONITOR_SUCCESS(WXMTJSBridge);
        WX_MONITOR_SUCCESS(WXMTNativeRender);
    }];
    [instance updatePerDicAfterCreateFinish];
}

- (void)updateFinish
{
    WXAssertComponentThread();
    
    WXSDKInstance *instance = self.weexInstance;
    WXComponent *root = [_indexDict objectForKey:WX_SDK_ROOT_REF];
    
    [self _addUITask:^{
        if (instance.updateFinish) {
            instance.updateFinish(root.view);
        }
    }];
}

- (void)refreshFinish
{
    WXAssertComponentThread();
    
    WXSDKInstance *instance = self.weexInstance;
    WXComponent *root = [_indexDict objectForKey:WX_SDK_ROOT_REF];
    
    [self _addUITask:^{
        if (instance.refreshFinish) {
            instance.refreshFinish(root.view);
        }
    }];
}

- (void)renderFinish
{
    WXAssertComponentThread();
    
    WXSDKInstance *instance  = self.weexInstance;
    [self _addUITask:^{
        UIView *rootView = instance.rootView;
        [instance.performance onInstanceRenderSuccess:instance];
        if (instance.renderFinish) {
            instance.renderFinish(rootView);
        }
    }];
}

- (void)renderFailed:(NSError *)error {
    WXAssertComponentThread();

    WXSDKInstance *instance  = self.weexInstance;
    [self _addUITask:^{
        if (instance.onFailed) {
            instance.onFailed(error);
        }
    }];
}

- (void)unload
{
    WXAssertComponentThread();
    [self invalidate];
    [self _stopDisplayLink];
    
    // first, unbind with underneath RenderObjects
    {
        NSEnumerator* enumerator = [_indexDict objectEnumerator];
        WXComponent *component;
        while ((component = [enumerator nextObject])) {
            [component _setRenderObject:nullptr];
        }
    }
    
    // second, unload views and finally release components in UI thread
    {
        __block WXComponent* rootComponent = _rootComponent;
        NSEnumerator *enumerator = [[_indexDict copy] objectEnumerator];
        dispatch_async(dispatch_get_main_queue(), ^{
            WXComponent *component;
            while ((component = [enumerator nextObject])) {
                [component _unloadViewWithReusing:NO];
            }
            rootComponent = nil; // finally release all components
        });
    }
    
    // clear containers
    _rootComponent = nil;
    [_indexDict removeAllObjects];
    [_fixedComponents removeAllObjects];
    [_uiTaskQueue removeAllObjects];
}

- (void)invalidate
{
    _isValid = NO;
}

- (BOOL)isValid
{
    return _isValid;
}

#pragma mark Display link task

- (void)_addVdomAndComponentCountTask
{
    __weak WXComponentManager* wself = self;
    [_displayTaskQueue addObject:[WXComponentThreadTickTask taskWithBlock:^{
        __strong WXComponentManager* sself = wself;
        if (sself) {
            if (sself->_maxComponentCount != sself->_maxComponentCountReported) {
                [sself.weexInstance.apmInstance updateMaxStats:KEY_PAGE_STATS_MAX_COMPONENT_NUM curMaxValue:sself->_maxComponentCount];
                sself->_maxComponentCountReported = sself->_maxComponentCount;
            }
            
            if (sself->_maxVdomDepth != sself->_maxVdomDepthReported) {
                [sself.weexInstance.apmInstance updateMaxStats:KEY_PAGE_STATS_MAX_DEEP_DOM curMaxValue:sself->_maxVdomDepth];
                sself->_maxVdomDepthReported = sself->_maxVdomDepth;
            }
        }
    } tickCount:30 /* triggered about every 500ms */]];
}

- (void)_startDisplayLink
{
    WXAssertComponentThread();
    [[WXDisplayLinkManager sharedInstance] registerDisplayClient:self];
    _displayTick = 0;
}

- (void)_stopDisplayLink
{
    WXAssertComponentThread();
    [[WXDisplayLinkManager sharedInstance] unregisterDisplayClient:self];
}

- (void)_suspendDisplayLink
{
    WXAssertComponentThread();
    _suspend = YES;
    [self _executeDisplayTask:YES]; // on suspend, executes every task once
}

- (void)_awakeDisplayLink
{
    WXAssertComponentThread();
    _suspend = NO;
    _displayTick = 0;
}

- (void)_handleDisplayLink
{
    WXAssertComponentThread();
    
    [self _layoutAndSyncUI];
    
    if (!_suspend) {
        // execute tasks in _displayTaskQueue
        _displayTick ++;
        [self _executeDisplayTask:NO];
    }
}

- (void)_executeDisplayTask:(BOOL)onSuspend
{
    for (WXComponentThreadTickTask* task in _displayTaskQueue) {
        if (onSuspend || (_displayTick % task.displayTickCount == 0)) {
            if (task.block) {
                task.block();
            }
        }
    }
}

- (void)_layoutAndSyncUI
{
    [self _layout];
    if(_uiTaskQueue.count > 0){
        [self _syncUITasks];
        _noTaskTickCount = 0;
    } else {
        // suspend display link when there's no task for 1 second, in order to save CPU time.
        _noTaskTickCount ++;
        if (_noTaskTickCount > 60) {
            [self _suspendDisplayLink];
        }
    }
}

- (void)_layout
{
    [WXCoreBridge layoutPage:_weexInstance.instanceId forced:[_rootComponent needsLayout]];
}

- (void) _printFlexComponentFrame:(WXComponent *)component
{
#ifdef DEBUG
    WXLogDebug(@"node ref:%@, type:%@ , frame:%@",
          component.ref,
          component.type,
          NSStringFromCGRect(component.view.layer.frame)
          );
#endif
    
    for (WXComponent *childComponent in component.subcomponents) {
        [self _printFlexComponentFrame:childComponent];
    }
}

- (void)_syncUITasks
{
    NSInteger mismatchBeginIndex = _uiTaskQueue.count;
    for (NSInteger i = _uiTaskQueue.count - 1;i >= 0;i --) {
        if (_uiTaskQueue[i] == WXPerformUITaskBatchEndBlock) {
            _syncUITaskCount = 0;
            // clear when find the matches for end and begin tag
            break;
        }
        if (_uiTaskQueue[i] == WXPerformUITaskBatchBeginBlock) {
            mismatchBeginIndex = i;
            break;
        }
    }
    
    if (mismatchBeginIndex == _uiTaskQueue.count) {//!OCLint
        // here we get end tag or there are not begin and end directives
    } else {
        _syncUITaskCount ++;
        // we only find begin tag but missing end tag,
        if (_syncUITaskCount > (MAX_DROP_FRAME_FOR_BATCH)) {
            // when the wait times come to MAX_DROP_FRAME_FOR_BATCH, we will pop all the stashed operations for user experience.
            mismatchBeginIndex = _uiTaskQueue.count;
            _syncUITaskCount = 0;
        }
    }
    
    if (mismatchBeginIndex > 0) {
        NSArray<dispatch_block_t> *blocks = [_uiTaskQueue subarrayWithRange:NSMakeRange(0, mismatchBeginIndex)];
        [_uiTaskQueue removeObjectsInRange:NSMakeRange(0, mismatchBeginIndex)];
        if (blocks.count) {
            dispatch_async(dispatch_get_main_queue(), ^{
                for(dispatch_block_t block in blocks) {
                    block();
                }
            });
        }
    }
}

#pragma mark Fixed 

- (void)addFixedComponent:(WXComponent *)fixComponent
{
    pthread_mutex_lock(&_propertyMutex);
    [_fixedComponents addObject:fixComponent];
    pthread_mutex_unlock(&_propertyMutex);
}

- (void)removeFixedComponent:(WXComponent *)fixComponent
{
    pthread_mutex_lock(&_propertyMutex);
    [_fixedComponents removeObject:fixComponent];
    pthread_mutex_unlock(&_propertyMutex);
}

#pragma mark Enumerating

- (void)enumerateComponentsUsingBlock:(void (^)(WXComponent *, BOOL *stop))block
{
    if (block == nil || _rootComponent == nil) {
        return;
    }
    
    NSMutableArray* components = [[NSMutableArray alloc] init];
    [components addObject:_rootComponent];
    
    while ([components count] > 0) {
        BOOL stop = NO;
        
        NSArray* thisLevelComponents = [components copy];
        [components removeAllObjects];
        
        // enumerate thisLevelComponents and add next level components to components
        for (WXComponent* c in thisLevelComponents) {
            block(c, &stop);
            if (stop) {
                break;
            }
            
            for (WXComponent* nextLevelComponent in c->_subcomponents) {
                [components addObject:nextLevelComponent];
            }
        }
        
        if (stop) {
            break;
        }
    }
}

static void (^WXPerformUITaskBatchBeginBlock)(void) = ^ () {
#if DEBUG
    WXLogDebug(@"directive BatchBeginBlock");
#endif
};
static void (^WXPerformUITaskBatchEndBlock)(void) = ^ () {
#if DEBUG
    WXLogDebug(@"directive BatchEndBlock");
#endif
};

- (void)performBatchBegin
{
    [self _addUITask:WXPerformUITaskBatchBeginBlock];
}

- (void)performBatchEnd
{
    [self _addUITask:WXPerformUITaskBatchEndBlock];
}

- (void)handleDisplayLink {
    [self _handleDisplayLink];
}

@synthesize suspend=_suspend;


@end

void WXPerformBlockOnComponentThread(void (^block)(void))
{
    [WXComponentManager _performBlockOnComponentThread:block];
}

void WXPerformBlockSyncOnComponentThread(void (^block)(void))
{
    [WXComponentManager _performBlockSyncOnComponentThread:block];
}
