/*
 * 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 "WXComponent.h"
#import "WXComponent_internal.h"
#import "WXComponentManager.h"
#import "WXSDKManager.h"
#import "WXSDKInstance.h"
#import "WXSDKInstance_private.h"
#import "WXDefine.h"
#import "WXLog.h"
#import "WXWeakObjectWrapper.h"
#import "WXUtility.h"
#import "WXConvert.h"
#import "WXMonitor.h"
#import "WXAssert.h"
#import "WXTransform.h"
#import "WXRoundedRect.h"
#import <pthread/pthread.h>
#import "WXComponent+PseudoClassManagement.h"
#import "WXComponent+BoxShadow.h"
#import "WXTracingManager.h"
#import "WXComponent+Events.h"
#import "WXComponent+Layout.h"
#import "WXConfigCenterProtocol.h"
#import "WXSDKEngine.h"
#import "WXSDKInstance_performance.h"
#import "WXComponent_performance.h"
#import "WXCoreBridge.h"

#pragma clang diagnostic ignored "-Wincomplete-implementation"
#pragma clang diagnostic ignored "-Wobjc-protocol-method-implementation"
static BOOL bInited = NO;
static BOOL bNeedRemoveEvents = YES;

@interface WXComponent () <UIGestureRecognizerDelegate>

@end

@implementation WXComponent
{
@private
    NSString *_ref;
    NSMutableDictionary *_styles;
    NSMutableDictionary *_attributes;
    NSMutableArray *_events;
    
    // Protects properties styles/attributes/events/subcomponents which will be accessed from multiple threads.
    pthread_mutex_t _propertyMutex;
    pthread_mutexattr_t _propertMutexAttr;
    
    __weak WXComponent *_supercomponent;
    __weak id<WXScrollerProtocol> _ancestorScroller;
    __weak WXSDKInstance *_weexInstance;
}

@synthesize transform = _transform;

#pragma mark Life Cycle

- (instancetype)initWithRef:(NSString *)ref
                       type:(NSString *)type
                     styles:(NSDictionary *)styles
                 attributes:(NSDictionary *)attributes
                     events:(NSArray *)events
               weexInstance:(WXSDKInstance *)weexInstance
{
    if (self = [super init]) {
        pthread_mutexattr_init(&_propertMutexAttr);
        pthread_mutexattr_settype(&_propertMutexAttr, PTHREAD_MUTEX_RECURSIVE);
        pthread_mutex_init(&_propertyMutex, &_propertMutexAttr);
        
        _ref = ref;
        _type = type;
        _weexInstance = weexInstance;
        _componentType = WXComponentTypeCommon;
        _styles = [self parseStyles:styles];
        _attributes = attributes ? [NSMutableDictionary dictionaryWithDictionary:attributes] : [NSMutableDictionary dictionary];
        _events = events ? [NSMutableArray arrayWithArray:events] : [NSMutableArray array];
        _subcomponents = [NSMutableArray array];
        _absolutePosition = CGPointMake(NAN, NAN);
        
        _displayType = WXDisplayTypeBlock;
        _isViewFrameSyncWithCalculated = YES;
        _ariaHidden = nil;
        _accessible = nil;
        _accessibilityHintContent = nil;
        
        _async = NO;
        
        if (styles[kWXTransitionProperty]) {
            _transition = [[WXTransition alloc]initWithStyles:styles];
        }

        //TODO set indicator style 
        if ([type isEqualToString:@"indicator"]) {
            _styles[@"position"] = @"absolute";
            if (!_styles[@"left"] && !_styles[@"right"]) {
                _styles[@"left"] = @0.0f;
            }
            if (!_styles[@"top"] && !_styles[@"bottom"]) {
                _styles[@"top"] = @0.0f;
            }
        }
        
        if (attributes[@"ariaHidden"]) {
            
            _ariaHidden = [WXConvert NSString:attributes[@"ariaHidden"]];
        }
        if (attributes[@"role"]) {
            _roles = attributes[@"role"];
        }
        if (attributes[@"ariaLabel"]) {
            _ariaLabel = [WXConvert NSString:attributes[@"ariaLabel"]];
        }
        if (attributes[@"accessible"]) {
            _accessible = [WXConvert NSString:attributes[@"accessible"]];
        }
        if(attributes[@"accessibilityHint"]) {
            _accessibilityHintContent = [WXConvert NSString:attributes[@"accessibilityHint"]];
        }
        if (attributes[@"groupAccessibilityChildren"]) {
            _groupAccessibilityChildren = [WXConvert NSString:attributes[@"groupAccessibilityChildren"]];
        }
        
        if (attributes[@"testId"]) {
            _testId = [WXConvert NSString:attributes[@"testId"]];
        }
        
        //may be removed when this feature is stable
        if (attributes[@"clipRadius"])
        {
            _clipRadius = [WXConvert NSString:attributes[@"clipRadius"]];
        }
        
#ifdef DEBUG
        WXLogDebug(@"flexLayout -> init component: ref : %@ , styles: %@",ref,styles);
        WXLogDebug(@"flexLayout -> init component: ref : %@ , attributes: %@",ref,attributes);
#endif
        [self _setupNavBarWithStyles:_styles attributes:_attributes];

        [self _initViewPropertyWithStyles:_styles];
        [self _initCompositingAttribute:_attributes];
        [self _handleBorders:styles isUpdating:NO];
        
        if (!bInited) {
            id<WXConfigCenterProtocol> configCenter = [WXSDKEngine handlerForProtocol:@protocol(WXConfigCenterProtocol)];
            if ([configCenter respondsToSelector:@selector(configForKey:defaultValue:isDefault:)]) {
                bNeedRemoveEvents = [[configCenter configForKey:@"iOS_weex_ext_config.removeEventsOfWXComponentWhenDealloc" defaultValue:@(YES) isDefault:NULL] boolValue];
                bInited = YES;
            }
        }
    }
    
    return self;
}

- (id)copyWithZone:(NSZone *)zone
{
    static std::atomic<long> __copy(0);
    long copyId = __copy ++;
    copyId %= (1024 * 1024);
    NSString *copyRef = [NSString stringWithFormat:@"%ldcopy_of%@", copyId, _isTemplate ? self.ref : self->_templateComponent.ref];
    
    // first, copy weex core render object
    void* copiedRenderObject = [WXCoreBridge copyRenderObject:_flexCssNode replacedRef:copyRef];
    WXAssert(copiedRenderObject != nullptr, @"cannot copy render object.");
    
    // second, alloc new WXComponent
    WXComponent *component = [[self class] allocWithZone:zone];
    [component _setRenderObject:copiedRenderObject];
    component = [component initWithRef:copyRef type:self.type styles:self.styles attributes:self.attributes events:self.events weexInstance:self.weexInstance];
    if (_isTemplate) {
        component->_templateComponent = self;
    }
    else {
        component->_templateComponent = self->_templateComponent;
    }
    component->_calculatedFrame = self.calculatedFrame;
    
    // third, copy children
    NSUInteger count = [self.subcomponents count];
    for (NSInteger i = 0; i < count; i ++) {
        WXComponent *subcomponentCopy = [[self.subcomponents objectAtIndex:i] copy];
        BOOL inserted = [component _insertSubcomponent:subcomponentCopy atIndex:i];
        if (inserted) {
            // add to layout tree
            [WXCoreBridge addChildRenderObject:subcomponentCopy->_flexCssNode toParent:component->_flexCssNode];
        }
        else {
            WXLogError(@"fail to insert copied component.");
        }
    }
    
    WXPerformBlockOnComponentThread(^{
        [self.weexInstance.componentManager addComponent:component toIndexDictForRef:copyRef];
    });
    
    return component;
}

- (UIAccessibilityTraits)_parseAccessibilityTraitsWithTraits:(UIAccessibilityTraits)trait roles:(NSString*)roleStr
{
    UIAccessibilityTraits newTrait = trait;
    for (NSString * role in [roleStr componentsSeparatedByString:@" "]) {
        newTrait |= [WXConvert WXUIAccessibilityTraits: role];
    }
    
    return newTrait;
}

- (void)dealloc
{
    if (_positionType == WXPositionTypeFixed) {
        [self.weexInstance.componentManager removeFixedComponent:self];
    }
    
    // remove all gesture and all
    if (_isTemplate && self.attributes[@"@templateId"]) {
        [[WXSDKManager bridgeMgr] callComponentHook:_weexInstance.instanceId componentId:self.attributes[@"@templateId"] type:@"lifecycle" hook:@"destroy" args:nil competion:nil];
    }
    if (_tapGesture) {
        [_tapGesture removeTarget:nil action:NULL];
    }
    if ([_swipeGestures count]) {
        for (UISwipeGestureRecognizer *swipeGestures in _swipeGestures) {
            [swipeGestures removeTarget:nil action:NULL];
        }
    }
    
    if (_longPressGesture) {
        [_longPressGesture removeTarget:nil action:NULL];
    }
    
    if (_panGesture) {
        [_panGesture removeTarget:nil action:NULL];
    }
    
    if (bNeedRemoveEvents) {
        if (WX_SYS_VERSION_LESS_THAN(@"9.0")) {
            [self _removeAllEvents];
        }
    }
    
    if (_bindingExpressions != nullptr) {
        for (WXJSExpression* expr : *_bindingExpressions) {
            if (expr != nullptr) {
                delete expr;
            }
        }
        delete _bindingExpressions;
    }

    pthread_mutex_destroy(&_propertyMutex);
    pthread_mutexattr_destroy(&_propertMutexAttr);
}

- (NSDictionary *)styles
{
    NSDictionary *styles;
    pthread_mutex_lock(&_propertyMutex);
    styles = _styles;
    pthread_mutex_unlock(&_propertyMutex);
    return styles;
}

- (NSDictionary *)pseudoClassStyles
{
    NSDictionary *pseudoClassStyles;
    pthread_mutex_lock(&_propertyMutex);
    pseudoClassStyles = _pseudoClassStyles;
    pthread_mutex_unlock(&_propertyMutex);
    
    return pseudoClassStyles;
}

- (NSString *)type
{
    return _type;
}

- (NSDictionary *)attributes
{
    NSDictionary *attributes;
    pthread_mutex_lock(&_propertyMutex);
    attributes = _attributes;
    pthread_mutex_unlock(&_propertyMutex);
    
    return attributes;
}

- (NSArray *)events
{
    NSArray *events;
    pthread_mutex_lock(&_propertyMutex);
    events = [_events copy];
    pthread_mutex_unlock(&_propertyMutex);
    
    return events;
}

- (void)setDisplayType:(WXDisplayType)displayType
{
    if (_displayType != displayType) {
        _displayType = displayType;
        if (displayType == WXDisplayTypeNone) {
            [self _removeFromSupercomponent];
            WXPerformBlockOnMainThread(^{
                [self removeFromSuperview];
            });
        } else {
            WXPerformBlockOnMainThread(^{
                [self _buildViewHierarchyLazily];
                // TODO: insert into the correct index
                [self.supercomponent.view addSubview:self.view];
            });
        }
        [self setNeedsLayout];
    }
}

- (WXSDKInstance *)weexInstance
{
    return _weexInstance;
}

- (NSString *)description
{
    return [NSString stringWithFormat:@"<%@:%p ref=%@> %@", _type, self, _ref, _view];
}

#pragma mark Property

- (UIView *)view
{
    if (_componentType != WXComponentTypeCommon) {
        return nil;
    }
    if ([self isViewLoaded]) {
        return _view;
    } else {
        WXAssertMainThread();
        
        // compositing child will be drew by its composited ancestor
        if (_isCompositingChild) {
            return nil;
        }
        
        [self viewWillLoad];
        
        _view = [self loadView];
#ifdef DEBUG
        WXLogDebug(@"flexLayout -> loadView:addr-(%p),componentRef-(%@)",_view,self.ref);
#endif
        _layer = _view.layer;
        _view.frame = [self _fixIllegalFrame:_calculatedFrame];
        _view.hidden = _visibility == WXVisibilityShow ? NO : YES;
        _view.clipsToBounds = _clipToBounds;
        if (![self _needsDrawBorder]) {
            _layer.borderColor = _borderTopColor.CGColor;
            _layer.borderWidth = _borderTopWidth;
            [self _resetNativeBorderRadius];
            _layer.opacity = _opacity;
            _view.backgroundColor = _backgroundColor;
        }

        if (_backgroundImage) {
            [self setGradientLayer];
        }

        if (_transform) {
            [_transform applyTransformForView:_view];
        }
        
        [self _adjustForRTL];
        
        if (_boxShadow) {
            [self configBoxShadow:_boxShadow];
        }
        
        _view.wx_component = self;
        _view.wx_ref = self.ref;
        _layer.wx_component = self;
        
        if (_roles) {
            [_view setAccessibilityTraits:[self _parseAccessibilityTraitsWithTraits:self.view.accessibilityTraits roles:_roles]];
        }
        
        if (_testId) {
            _view.accessibilityIdentifier = _testId;
        }
        
        if (_accessibilityHintContent) {
            [_view setAccessibilityHint:_accessibilityHintContent];
        }
        
        if (_ariaLabel) {
            _view.accessibilityLabel = _ariaLabel;
        }
        if (_accessible) {
            [_view setIsAccessibilityElement:[WXConvert BOOL:_accessible]];
        }
        
        if (_ariaHidden) {
            [_view setAccessibilityElementsHidden:[WXConvert BOOL:_ariaHidden]];
        }
        if (_groupAccessibilityChildren) {
            [_view setShouldGroupAccessibilityChildren:[WXConvert BOOL:_groupAccessibilityChildren]];
        }
        
        [self _initEvents:self.events];
        [self _initPseudoEvents:_isListenPseudoTouch];
        
        if (_positionType == WXPositionTypeSticky) {
            [self.ancestorScroller addStickyComponent:self];
        }
        
        if (self.supercomponent && self.supercomponent->_async) {
            self->_async = YES;
        }
        
        [self setNeedsDisplay];
        [[NSNotificationCenter defaultCenter] postNotificationName:WX_COMPONENT_NOTIFICATION_VIEW_LOADED object:self];
        [self viewDidLoad];
        
        if (_lazyCreateView) {
            [self _buildViewHierarchyLazily];
        }

        [self _handleFirstScreenTime];
        
        [self.weexInstance.performance onViewLoad:self];
        return _view;
    }
}

- (CGRect)_fixIllegalFrame:(CGRect)frame{
    CGPoint origin = frame.origin;
    CGSize size = frame.size;
    CGRect fixedFrame = CGRectMake(isnan(origin.x)?0.0f:origin.x
                                   , isnan(origin.y)?0.0f:origin.y
                                   , isnan(size.width)?0.0f:size.width
                                   , isnan(size.height)?0.0f:size.height);
    return fixedFrame;
}

- (void)_buildViewHierarchyLazily
{
    if (self.supercomponent && !((WXComponent *)self.supercomponent)->_lazyCreateView) {
        NSArray *subcomponents = ((WXComponent *)self.supercomponent).subcomponents;
        
        NSInteger index = [subcomponents indexOfObject:self];
        if (index != NSNotFound) {
            [(WXComponent *)self.supercomponent insertSubview:self atIndex:index];
        }
    }
    
    NSArray *subcomponents = self.subcomponents;
    for (int i = 0; i < subcomponents.count; i++) {
        WXComponent *subcomponent = subcomponents[i];
        [self insertSubview:subcomponent atIndex:i];
    }
}

- (void)_resetNativeBorderRadius
{
    WXRoundedRect *borderRect = [[WXRoundedRect alloc] initWithRect:_calculatedFrame topLeft:_borderTopLeftRadius topRight:_borderTopRightRadius bottomLeft:_borderBottomLeftRadius bottomRight:_borderBottomRightRadius];
    _layer.cornerRadius = borderRect.radii.topLeft;
}

- (void)_handleFirstScreenTime
{
    if (WX_MONITOR_INSTANCE_PERF_IS_RECORDED(WXPTFirstScreenRender, self.weexInstance)) {
        return;
    }
    CGPoint absolutePosition = [self.supercomponent.view convertPoint:_view.frame.origin toView:_weexInstance.rootView];
    if (absolutePosition.y + _view.frame.size.height > self.weexInstance.rootView.frame.size.height + 1) {
        WX_MONITOR_INSTANCE_PERF_END(WXPTFirstScreenRender, self.weexInstance);
    }
}

- (BOOL)_isAffineTypeAs:(NSString *)type
{
    return [WXCoreBridge isComponentAffineType:_type asType:type];
}

- (CALayer *)layer
{
    return _layer;
}

- (CGRect)calculatedFrame
{
    return _calculatedFrame;
}

- (CGFloat)_getInnerContentMainSize
{
    return -1.0f;
}

- (void)_assignInnerContentMainSize:(CGFloat)value
{
}

- (BOOL)_isCalculatedFrameChanged:(CGRect)frame
{
    return !CGRectEqualToRect(frame, _calculatedFrame);
}

- (void)_layoutPlatform
{
}

- (void)_assignCalculatedFrame:(CGRect)frame
{
    _calculatedFrame = frame;
}

- (CGPoint)absolutePosition
{
    return _absolutePosition;
}

- (void)_addEventParams:(NSDictionary *)params
{
    pthread_mutex_lock(&_propertyMutex);
    if (!_eventParameters) {
        _eventParameters = [NSMutableDictionary dictionary];
    }
    [_eventParameters addEntriesFromDictionary:params];
    pthread_mutex_unlock(&_propertyMutex);
}

- (NSArray *)_paramsForEvent:(NSString *)eventName
{
    NSArray *params;
    pthread_mutex_lock(&_propertyMutex);
    params = _eventParameters[eventName];
    pthread_mutex_unlock(&_propertyMutex);
    
    return params;
}

#pragma mark Component Hierarchy 

- (NSArray<WXComponent *> *)subcomponents
{
    NSArray<WXComponent *> *subcomponents;
    pthread_mutex_lock(&_propertyMutex);
    subcomponents = [_subcomponents copy];
    pthread_mutex_unlock(&_propertyMutex);
    
    return subcomponents;
}

- (WXComponent *)supercomponent
{
    return _supercomponent;
}

- (BOOL)_insertSubcomponent:(WXComponent *)subcomponent atIndex:(NSInteger)index
{
    WXAssert(subcomponent, @"The subcomponent to insert to %@ at index %d must not be nil", self, index);
    
    if (subcomponent == nil) {
        return NO;
    }
    
    if (index > [_subcomponents count]) {
        WXLogError(@"the index of inserted %ld is out of range as the current is %lu", (long)index, (unsigned long)[_subcomponents count]);
        return NO;
    }
    
    subcomponent->_supercomponent = self;
    
    pthread_mutex_lock(&_propertyMutex);
    [_subcomponents insertObject:subcomponent atIndex:index];
    pthread_mutex_unlock(&_propertyMutex);
    
    if (subcomponent->_positionType == WXPositionTypeFixed) {
        subcomponent.ignoreInteraction = YES;
        [self.weexInstance.componentManager addFixedComponent:subcomponent];
    }
    
    if (_useCompositing || _isCompositingChild) {
        subcomponent->_isCompositingChild = YES;
    }
    
    [self setNeedsLayout];
    
    return YES;
}

- (void)_removeSubcomponent:(WXComponent *)subcomponent removeCssNode:(BOOL)removeCssNode
{
    pthread_mutex_lock(&_propertyMutex);
    [_subcomponents removeObject:subcomponent];
    if (removeCssNode) {
        [self removeSubcomponentCssNode:subcomponent];
    }
    pthread_mutex_unlock(&_propertyMutex);
}

- (void)_removeFromSupercomponent
{
    [self _removeFromSupercomponent:YES]; // really do remove
}

- (void)_removeFromSupercomponent:(BOOL)remove
{
    [self.supercomponent _removeSubcomponent:self removeCssNode:remove];
    [self.supercomponent setNeedsLayout];
    
    if (_positionType == WXPositionTypeFixed) {
        [self.weexInstance.componentManager removeFixedComponent:self];
    }
    if (_positionType == WXPositionTypeSticky) {
        [self.ancestorScroller removeStickyComponent:self];
    }
}

- (void)_moveToSupercomponent:(WXComponent *)newSupercomponent atIndex:(NSUInteger)index
{
    [self _removeFromSupercomponent:NO]; // no remove underlayer render object
    [newSupercomponent _insertSubcomponent:self atIndex:index];
}

- (void)_didInserted
{
}

- (id<WXScrollerProtocol>)ancestorScroller
{
    if(!_ancestorScroller) {
        WXComponent *supercomponent = self.supercomponent;
        while (supercomponent) {
            if([supercomponent conformsToProtocol:@protocol(WXScrollerProtocol)]) {
                _ancestorScroller = (id<WXScrollerProtocol>)supercomponent;
                break;
            }
            supercomponent = supercomponent.supercomponent;
        }
    }
    
    return _ancestorScroller;
}

#pragma mark Updating

- (BOOL)_isTransitionNone
{
    return _transition == nil || _transition.transitionOptions == WXTransitionOptionsNone;
}

- (BOOL)_hasTransitionPropertyInStyles:(NSDictionary *)styles
{
    return [_transition _hasTransitionOptionInStyles:styles];
}

- (void)_updateStylesOnComponentThread:(NSDictionary *)styles resetStyles:(NSMutableArray *)resetStyles isUpdateStyles:(BOOL)isUpdateStyles
{
    BOOL isTransitionTag = _transition ? [self _isTransitionTag:styles] : NO;
    if (isTransitionTag) {
        [_transition _handleTransitionWithStyles:[styles mutableCopy] resetStyles:resetStyles target:self];
    } else {
        styles = [self parseStyles:styles];
        [self _updateCSSNodeStyles:styles];
        [self _resetCSSNodeStyles:resetStyles];
    }
    if (isUpdateStyles) {
        [self _modifyStyles:styles];
        if ([self needsLayout]) {
            // call update style may take effect on layout, maybe the component
            // displaylink has been paused, so we need to restart the component task, and it will auto-pause when task queue is empty.
            [self.weexInstance.componentManager startComponentTasks];
        }
    }
}

- (BOOL)_isTransitionTag:(NSDictionary *)styles
{
    BOOL yesOrNo = false;
    if (_transition.transitionOptions != WXTransitionOptionsNone) {
        yesOrNo = true;
    }
    return yesOrNo;
}

- (BOOL)_isTransitionOnMainThreadStyles:(NSDictionary *)styles
{
    BOOL yesOrNo = false;
    if (_transition.transitionOptions != WXTransitionOptionsNone) {
        if ((_transition.transitionOptions & WXTransitionOptionsBackgroundColor &&styles[@"backgroundColor"])
            ||(_transition.transitionOptions & WXTransitionOptionsTransform &&styles[@"transform"])
            ||(_transition.transitionOptions & WXTransitionOptionsOpacity &&styles[@"opacity"])) {
            yesOrNo = true;
        }
    }
    return yesOrNo;
}

- (void)_modifyStyles:(NSDictionary *)styles
{
    pthread_mutex_lock(&_propertyMutex);
    [_styles addEntriesFromDictionary:styles];
    pthread_mutex_unlock(&_propertyMutex);
}

- (void)_updateAttributesOnComponentThread:(NSDictionary *)attributes
{
    pthread_mutex_lock(&_propertyMutex);
    [_attributes addEntriesFromDictionary:attributes];
    pthread_mutex_unlock(&_propertyMutex);
}

- (void)_addEventOnComponentThread:(NSString *)eventName
{
    pthread_mutex_lock(&_propertyMutex);
    [_events addObject:eventName];
    pthread_mutex_unlock(&_propertyMutex);
}

- (void)_removeEventOnComponentThread:(NSString *)eventName
{
    pthread_mutex_lock(&_propertyMutex);
    [_events removeObject:eventName];
    pthread_mutex_unlock(&_propertyMutex);
}

- (void)_updateStylesOnMainThread:(NSDictionary *)styles resetStyles:(NSMutableArray *)resetStyles
{
    WXAssertMainThread();
    if (![self _isTransitionOnMainThreadStyles:styles]) {
        [self _updateViewStyles:styles];
    } else {
        [self _transitionUpdateViewProperty:styles];
    }
#ifdef DEBUG
    NSDictionary *copySelfStyle = [NSDictionary dictionaryWithDictionary:self.styles];
    WXLogDebug(@"flexLayout -> ref:%@ style before : %@",self.ref,copySelfStyle);
    
    if (styles) {
        WXLogDebug(@"flexLayout -> ref:%@ update styles : %@",self.ref,styles);
    }
    
    if (resetStyles) {
        WXLogDebug(@"flexLayout -> ref:%@ update resetStyles : %@",self.ref,resetStyles);
    }
#endif
    
    [self _resetStyles:resetStyles];
    [self _handleBorders:styles isUpdating:YES];
    [self updateStyles:styles];
    [self resetStyles:resetStyles];
    
#ifdef DEBUG
    //self.styles may change
    copySelfStyle = [NSDictionary dictionaryWithDictionary:self.styles];
    WXLogDebug(@"flexLayout -> ref:%@ style after : %@",self.ref,copySelfStyle);
#endif
}

- (void)_updateAttributesOnMainThread:(NSDictionary *)attributes
{
    WXAssertMainThread();
    
    [self _updateNavBarAttributes:attributes];
    
    [self updateAttributes:attributes];
    [self _configWXComponentA11yWithAttributes:attributes];
}

- (void)updateStyles:(NSDictionary *)styles
{
    WXAssertMainThread();
}

- (void)updateAttributes:(NSDictionary *)attributes
{
    WXAssertMainThread();
}

- (void)setNativeTransform:(CGAffineTransform)transform
{
    WXAssertMainThread();
    
    self.transform = [[WXTransform alloc] initWithNativeTransform:CATransform3DMakeAffineTransform(transform) instance:self.weexInstance];
    if (!CGRectEqualToRect(self.calculatedFrame, CGRectZero)) {
        [_transform applyTransformForView:_view];
        [self _adjustForRTL];
        [_layer setNeedsDisplay];
    }
}

- (void)readyToRender
{
    if (self.weexInstance.trackComponent) {
        [self.supercomponent readyToRender];
    }
}


- (void)setGradientLayer
{
    if (CGRectEqualToRect(self.view.frame, CGRectZero)) {
        return;
    }
    NSDictionary * linearGradient = [WXUtility linearGradientWithBackgroundImage:_backgroundImage];
    if (!linearGradient) {
        return ;
    }
    
    __weak typeof(self) weakSelf = self;
    dispatch_async(dispatch_get_main_queue(), ^{
        __strong typeof(self) strongSelf = weakSelf;
        if(strongSelf) {
            UIColor * startColor = (UIColor*)linearGradient[@"startColor"];
            UIColor * endColor = (UIColor*)linearGradient[@"endColor"];
            CAGradientLayer * gradientLayer = [WXUtility gradientLayerFromColors:@[startColor, endColor] locations:nil frame:strongSelf.view.bounds gradientType:(WXGradientType)[linearGradient[@"gradientType"] integerValue]];
            if (gradientLayer) {
                _backgroundColor = [UIColor colorWithPatternImage:[strongSelf imageFromLayer:gradientLayer]];
                strongSelf.view.backgroundColor = _backgroundColor;
            }
        }
    });
}

- (void)_configWXComponentA11yWithAttributes:(NSDictionary *)attributes
{
    WX_CHECK_COMPONENT_TYPE(self.componentType)
    if (attributes[@"role"]){
        _roles = attributes[@"role"];
        [self.view setAccessibilityTraits:[self _parseAccessibilityTraitsWithTraits:self.view.accessibilityTraits roles:_roles]];
    }
    if (attributes[@"ariaHidden"]) {
        _ariaHidden = [WXConvert NSString:attributes[@"ariaHidden"]];
        [self.view setAccessibilityElementsHidden:[WXConvert BOOL:_ariaHidden]];
    }
    if (attributes[@"accessible"]) {
        _accessible = [WXConvert NSString:attributes[@"accessible"]];
        [self.view setIsAccessibilityElement:[WXConvert BOOL:_accessible]];
    }
    if (attributes[@"ariaLabel"]) {
        _ariaLabel = [WXConvert NSString:attributes[@"ariaLabel"]];
        self.view.accessibilityValue = _ariaLabel;
    }
    if (attributes[@"accessibilityHint"]) {
        _accessibilityHintContent = [WXConvert NSString:attributes[@"accessibilityHint"]];
        [self.view setAccessibilityHint:_accessibilityHintContent];
    }
    
    if (attributes[@"groupAccessibilityChildren"]) {
        _groupAccessibilityChildren = [WXConvert NSString:attributes[@"groupAccessibilityChildren"]];
        [self.view setShouldGroupAccessibilityChildren:[WXConvert BOOL:_groupAccessibilityChildren]];
    }

    
    if (attributes[@"testId"]) {
        [self.view setAccessibilityIdentifier:[WXConvert NSString:attributes[@"testId"]]];
    }

}

- (UIImage *)imageFromLayer:(CALayer *)layer
{
    UIGraphicsBeginImageContextWithOptions(layer.frame.size, NO, 0);
    [layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage *outputImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return outputImage;
}

#pragma mark Reset
- (void)resetStyles:(NSArray *)styles
{
    WXAssertMainThread();
}

#pragma mark Layout

/**
 *  @see WXComponent+Layout.m
 */

#pragma mark View Management

/**
 *  @see WXComponent+ViewManagement.m
 */

#pragma mark Events

/**
 *  @see WXComponent+Events.m
 */

#pragma mark Display

/**
 *  @see WXComponent+Display.m
 */

@end


@implementation UIView (WXComponent)

- (WXComponent *)wx_component
{
    WXWeakObjectWrapper *weakWrapper = objc_getAssociatedObject(self, @selector(wx_component));
    return [weakWrapper weakObject];
}

- (void)setWx_component:(WXComponent *)wx_component
{
    id weakWrapper = [[WXWeakObjectWrapper alloc] initWithWeakObject:wx_component];
    objc_setAssociatedObject(self, @selector(wx_component), weakWrapper, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (NSString *)wx_ref
{
    WXWeakObjectWrapper *weakWrapper = objc_getAssociatedObject(self, @selector(wx_ref));
    return [weakWrapper weakObject];
}

- (void)setWx_ref:(NSString *)wx_ref
{
    id weakWrapper = [[WXWeakObjectWrapper alloc] initWithWeakObject:wx_ref];
    objc_setAssociatedObject(self, @selector(wx_ref), weakWrapper, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

@end

@implementation CALayer (WXComponents_new)

- (WXComponent *)wx_component
{
    WXWeakObjectWrapper *weakWrapper = objc_getAssociatedObject(self, @selector(wx_component));
    return [weakWrapper weakObject];
}

- (void)setWx_component:(WXComponent *)wx_component
{
    id weakWrapper = [[WXWeakObjectWrapper alloc] initWithWeakObject:wx_component];
    objc_setAssociatedObject(self, @selector(wx_component), weakWrapper, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

@end
