/*
 * 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 "WXRichText.h"
#import "WXSDKManager.h"
#import "WXSDKEngine.h"
#import "WXConvert.h"
#import "WXSDKInstance.h"
#import "WXComponent+Layout.h"
#import "WXNavigationProtocol.h"
#import "WXImgLoaderProtocol.h"
#import "WXComponentManager.h"
#import "WXLog.h"
#import "WXDarkThemeProtocol.h"
#include <pthread/pthread.h>

@interface WXRichNode : NSObject

@property (nonatomic, strong) NSString  *type;
@property (nonatomic, strong) NSString  *ref;
@property (nonatomic, strong) NSString  *text;
@property (nonatomic, strong) UIColor   *color;
@property (nonatomic, strong) UIColor   *darkThemeColor;
@property (nonatomic, strong) UIColor   *backgroundColor;
@property (nonatomic, strong) UIColor   *darkThemeBackgroundColor;
@property (nonatomic, strong) NSString  *fontFamily;
@property (nonatomic, assign) CGFloat   fontSize;
@property (nonatomic, assign) CGFloat   fontWeight;
@property (nonatomic, assign) WXTextStyle  fontStyle;
@property (nonatomic, assign) WXTextDecoration textDecoration;
@property (nonatomic, strong) NSString  *pseudoRef;
@property (nonatomic, assign) CGFloat width;
@property (nonatomic, assign) CGFloat height;
@property (nonatomic, strong) NSURL *href;
@property (nonatomic, strong) NSURL *src;
@property (nonatomic, assign) NSRange range;
@property (nonatomic, strong) NSMutableArray *childNodes;

@end

@implementation WXRichNode
- (instancetype)init
{
    if (self = [super init]) {
        _childNodes = [[NSMutableArray alloc] init];
    }
    return self;
}

@end

@interface WXRichTextView : UITextView

@end

@implementation WXRichTextView

- (instancetype)initWithFrame:(CGRect)frame
{
    if ((self = [super initWithFrame:frame])) {
        self.isAccessibilityElement = YES;
        self.accessibilityTraits |= UIAccessibilityTraitStaticText;
        self.opaque = NO;
        self.editable = NO;
        self.selectable = YES;
        self.contentMode = UIViewContentModeRedraw;
        self.textContainerInset = UIEdgeInsetsZero;
        self.textContainer.lineFragmentPadding = 0.0f;
        self.textContainer.lineBreakMode = NSLineBreakByClipping;
    }
    return self;
}

@end

#define WX_STYLE_FILL_RICHTEXT(key, type)\
do {\
    id value = styles[@#key]; \
    if (value) { \
        node.key = [WXConvert type:value];\
    } else if (!([@#key isEqualToString:@"backgroundColor"] || \
        [@#key isEqualToString:@"darkThemeBackgroundColor"] || \
        [@#key isEqualToString:@"textDecoration"]) && superNode.key ) { \
        node.key = superNode.key; \
    } \
} while(0);

#define WX_STYLE_FILL_RICHTEXT_PIXEL(key)\
do {\
    id value = styles[@#key];\
    if (value) {\
        node.key = [WXConvert WXPixelType:value scaleFactor:self.weexInstance.pixelScaleFactor];\
    } else if (superNode.key ) { \
        node.key = superNode.key; \
    } \
} while(0);


@implementation WXRichText
{
    WXRichTextView *textView;
    NSMutableArray *_richNodes;
    NSMutableDictionary *_nodeRanges;
    NSMutableDictionary *_styles;
    NSMutableDictionary *_attributes;
    NSTextAlignment _textAlign;
    UIColor *_backgroundColor;
    pthread_mutex_t _attributedStringMutex;
    pthread_mutexattr_t _propertMutexAttr;
    CGFloat _lineHeight;
}

- (void)dealloc
{
    pthread_mutex_destroy(&_attributedStringMutex);
    pthread_mutexattr_destroy(&_propertMutexAttr);
}

- (WXRichTextView *)textView
{
    if (!textView) {
        textView = [[WXRichTextView alloc]init];
        textView.delegate = self;
        textView.scrollEnabled = NO;
    }
    return textView;
}

- (instancetype)initWithRef:(NSString *)ref
                       type:(NSString *)type
                     styles:(NSDictionary *)styles
                 attributes:(NSDictionary *)attributes
                     events:(NSArray *)events
               weexInstance:(WXSDKInstance *)weexInstance
{
    self = [super initWithRef:ref type:type styles:styles attributes:attributes events:events weexInstance:weexInstance];
    if (self) {
        _richNodes = [NSMutableArray new];
        _nodeRanges = [NSMutableDictionary new];
        _styles = [NSMutableDictionary dictionaryWithDictionary:styles];
        _attributes = [NSMutableDictionary dictionaryWithDictionary:attributes];
        _textAlign = styles[@"textAlign"] ? [WXConvert NSTextAlignment:styles[@"textAlign"]] : NSTextAlignmentLeft;
        _lineHeight = styles[@"lineHeight"] ? [WXConvert CGFloat:styles[@"lineHeight"]] / 2: 0;
        pthread_mutexattr_init(&(_propertMutexAttr));
        pthread_mutexattr_settype(&(_propertMutexAttr), PTHREAD_MUTEX_RECURSIVE);
        pthread_mutex_init(&(_attributedStringMutex), &(_propertMutexAttr));
    }
    return self;
}

- (void)fillAttributes:(NSDictionary *)attributes
{
    id value = attributes[@"value"];
    if (!value) {
        return;
    }
    if ([value isKindOfClass:[NSString class]]) {
        value = [WXUtility objectFromJSON:value];
    }
    if ([value isKindOfClass: [NSArray class]]) {
        [_richNodes removeAllObjects];
        
        WXRichNode *rootNode = [[WXRichNode alloc]init];
        [_richNodes addObject:rootNode];
        
        rootNode.type = @"root";
        if (_styles) {
            [self fillCSSStyles:_styles toNode:rootNode superNode:nil];
        }
        
        for (NSDictionary *dict in value) {
            [self recursivelyAddChildNode:dict toSuperNode:rootNode];
        }
        
        _backgroundColor = rootNode.backgroundColor?:[UIColor whiteColor];
    }
}

- (void)fillCSSStyles:(NSDictionary *)styles toNode:(WXRichNode *)node superNode:(WXRichNode *)superNode
{
    WX_STYLE_FILL_RICHTEXT(color, UIColor)
    WX_STYLE_FILL_RICHTEXT(darkThemeColor, UIColor)
    WX_STYLE_FILL_RICHTEXT(backgroundColor, UIColor)
    WX_STYLE_FILL_RICHTEXT(darkThemeBackgroundColor, UIColor)
    WX_STYLE_FILL_RICHTEXT(fontFamily, NSString)
    WX_STYLE_FILL_RICHTEXT_PIXEL(fontSize)
    WX_STYLE_FILL_RICHTEXT(fontWeight, WXTextWeight)
    WX_STYLE_FILL_RICHTEXT(fontStyle, WXTextStyle)
    WX_STYLE_FILL_RICHTEXT(textDecoration, WXTextDecoration)
    WX_STYLE_FILL_RICHTEXT_PIXEL(width)
    WX_STYLE_FILL_RICHTEXT_PIXEL(height)
}

- (void)fillAttributes:(NSDictionary *)attributes toNode:(WXRichNode *)node superNode:(WXRichNode *)superNode
{
    if (attributes[@"pseudoRef"]) {
        node.pseudoRef = attributes[@"pseudoRef"];
        node.href = [NSURL URLWithString:@"click://"];
    }
    
    if (attributes[@"href"]) {
        node.href = [NSURL URLWithString:attributes[@"href"]];
    }
    else if (superNode.href) {
        node.href = superNode.href;
        if (!(node.pseudoRef.length) && superNode.pseudoRef.length) {
            node.pseudoRef = superNode.pseudoRef;
        }
    }
    
    if (attributes[@"src"]) {
        node.src = [NSURL URLWithString:attributes[@"src"]];
    }
    
    if (attributes[@"value"] ) {
        id value = attributes[@"value"];
        if ([value isKindOfClass:[NSString class]]) {
            node.text = (NSString *)value;
        }
    }
}

- (void)recursivelyAddChildNode:(NSDictionary *)nodeValue toSuperNode:(WXRichNode *)superNode
{
    if (![nodeValue isKindOfClass:[NSDictionary class]]) {
        WXLogError(@"Invalid rich text structure.");
        return;
    }
    
    if (![nodeValue[@"type"] isKindOfClass:[NSString class]]) {
        WXLogError(@"Invalid rich text structure.");
        return;
    }
    
    WXRichNode *node = [[WXRichNode alloc]init];
    [_richNodes addObject:node];
    
    node.type = nodeValue[@"type"];

    [self fillCSSStyles:nodeValue[@"style"] toNode:node superNode:superNode];

    if (nodeValue[@"attr"]) {
        [self fillAttributes:nodeValue[@"attr"] toNode:node superNode:superNode];
    }
    
    if (nodeValue[@"children"]) {
        id value = nodeValue[@"children"];
        if ([value isKindOfClass:[NSArray class]]) {
            NSArray *children = (NSArray *)value;
            for(NSDictionary *childValue in children){
                [self recursivelyAddChildNode:childValue toSuperNode:node];
            }
        }
    }
}

- (WXRichNode*)findRichNode:(NSString*)ref {
    NSMutableArray *array = [NSMutableArray arrayWithArray:_richNodes];
    for (WXRichNode* node in array) {
        if ([node.ref isEqualToString:ref]) {
            return node;
        }
    }
    return nil;
}

- (NSInteger)indexOfRichNode:(WXRichNode*)node {
    NSInteger index = -1;
    NSMutableArray *array = [NSMutableArray arrayWithArray:_richNodes];
    for (WXRichNode* item in array) {
        if ([item.ref isEqualToString:node.ref]) {
            return index+1;
        }
        index++;
    }
    return index;
}

- (void)removeChildNode:(NSString*)ref superNodeRef:(NSString *)superNodeRef {
    WXRichNode* node = [self findRichNode:ref];
    WXRichNode* superNode = [self findRichNode:@"_root"];
    if (superNodeRef.length > 0) {
        superNode = [self findRichNode:superNodeRef];
    }
    if (superNode) {
         [superNode.childNodes removeObject:node];
    }
    [_richNodes removeObject:node];
    [self setNeedsLayout];
    [self innerLayout];
}

- (void)addChildNode:(NSString *)type ref:(NSString*)ref styles:(NSDictionary*)styles attributes:(NSDictionary*)attributes  toSuperNodeRef:(NSString *)superNodeRef {
    if ([_richNodes count] == 0) {
        WXRichNode *rootNode = [[WXRichNode alloc]init];
        [_richNodes addObject:rootNode];
        rootNode.type = @"root";
        rootNode.ref = @"_root";
        if (_styles) {
            [self fillCSSStyles:_styles toNode:rootNode superNode:nil];
        }
        _backgroundColor = rootNode.backgroundColor?:[UIColor whiteColor];
    }

    WXRichNode* superNode = [self findRichNode:@"_root"];
    if (superNodeRef.length > 0) {
        superNode = [self findRichNode:superNodeRef];
    }

    WXRichNode *node = [[WXRichNode alloc]init];
    node.ref = ref;
    NSInteger index = [self indexOfRichNode:superNode];
    if (index < 0) {
        return;
    }
    if (index == 0) {
        [_richNodes addObject:node];
    } else {
        [_richNodes insertObject:node atIndex:(index + superNode.childNodes.count + 1)];
    }
    [superNode.childNodes addObject:node];
    node.type = type;

    [self fillCSSStyles:styles toNode:node superNode:superNode];
    [self fillAttributes:attributes toNode:node superNode:superNode];
    [self setNeedsLayout];
    [self innerLayout];
}

#pragma mark - Subclass

- (UIView *)loadView
{
    return  [self textView];
}

- (void)viewDidUnload
{
    textView = nil;
}

- (void)viewDidLoad
{
    [self innerLayout];
}

- (void)layoutDidFinish
{
    [self innerLayout];
}

- (void)innerLayout
{
    __weak typeof(self) wself = self;
    WXPerformBlockOnComponentThread(^{
        __strong typeof(wself) sself = wself;
        if (sself) {
            if (sself.flexCssNode == nullptr) {
                return;
            }
            UIEdgeInsets padding = {
                WXFloorPixelValue(sself.flexCssNode->getPaddingTop()+sself.flexCssNode->getBorderWidthTop()),
                WXFloorPixelValue(sself.flexCssNode->getPaddingLeft()+sself.flexCssNode->getBorderWidthLeft()),
                WXFloorPixelValue(sself.flexCssNode->getPaddingBottom()+sself.flexCssNode->getBorderWidthBottom()),
                WXFloorPixelValue(sself.flexCssNode->getPaddingRight()+sself.flexCssNode->getBorderWidthRight())
            };
            
            NSMutableAttributedString* attrString = [sself buildAttributeString];
            WXPerformBlockOnMainThread(^{
                WXRichTextView* view = [sself textView];
                view.attributedText = attrString;
                view.textContainerInset = padding;
                view.backgroundColor = [UIColor clearColor];
            });
        }
    });
}

- (CGSize (^)(CGSize))measureBlock
{
    __weak typeof(self) weakSelf = self;
    
    return ^CGSize (CGSize constrainedSize) {
        
        NSMutableAttributedString *attributedString = [weakSelf buildAttributeString];
        
        CGFloat width = constrainedSize.width;
        if (isnan(width)) {
            width = CGFLOAT_MAX;
        }
        
        CGRect rect = [attributedString boundingRectWithSize:CGSizeMake(width, CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading context:nil];
        CGSize computedSize = rect.size;
        if(weakSelf.flexCssNode != nullptr){
            if (!isnan(weakSelf.flexCssNode->getMinWidth())) {
                computedSize.width = MAX(computedSize.width, weakSelf.flexCssNode->getMinWidth());
            }
            if (!isnan(weakSelf.flexCssNode->getMaxWidth())) {
                computedSize.width = MIN(computedSize.width, weakSelf.flexCssNode->getMaxWidth());
            }
            if (!isnan(weakSelf.flexCssNode->getMinHeight())) {
                computedSize.width = MAX(computedSize.height, weakSelf.flexCssNode->getMinHeight());
            }
            if (!isnan(weakSelf.flexCssNode->getMaxHeight())) {
                computedSize.width = MIN(computedSize.height, weakSelf.flexCssNode->getMaxHeight());
            }
        }
        return (CGSize) {
            WXCeilPixelValue(computedSize.width),
            WXCeilPixelValue(computedSize.height)
        };
    };
}

- (void)themeDidChange:(NSString*)theme
{
    [super themeDidChange:theme];
    if ([self isViewLoaded]) {
        // Force inner layout
        [self innerLayout];
    }
}

#pragma mark Text Building

- (NSMutableAttributedString *)buildAttributeString
{
    pthread_mutex_lock(&(_attributedStringMutex));
    [self fillAttributes:_attributes];
    NSMutableArray *array = [NSMutableArray arrayWithArray:_richNodes];
    pthread_mutex_unlock(&(_attributedStringMutex));
    
    NSMutableDictionary *nodeRange = [NSMutableDictionary dictionary];
    NSMutableAttributedString *attrStr = [[NSMutableAttributedString alloc] init];
    NSUInteger location;
    
    BOOL invert = self.invertForDarkTheme;
    
    // Invert default background color.
    UIColor* defaultTextColor = [UIColor blackColor];
    UIColor* defaultBackgroundColor = _backgroundColor;
    if (invert && [self.weexInstance isDarkTheme]) {
        defaultTextColor = [[WXSDKInstance darkThemeColorHandler] getInvertedColorFor:[UIColor blackColor] ofScene:[self colorSceneType] withDefault:[UIColor blackColor]];
        defaultBackgroundColor = [[WXSDKInstance darkThemeColorHandler] getInvertedColorFor:_backgroundColor ofScene:[self colorSceneType] withDefault:_backgroundColor];
    }
    
    __weak typeof(self) weakSelf = self;
    for (WXRichNode *node in array) {
        location = attrStr.length;
        
        if ([node.type isEqualToString:@"span"]) {
            if (node.text && [node.text length] > 0) {
                NSString *text = node.text;
                [attrStr.mutableString appendString:text];
                
                NSRange range = NSMakeRange(location, text.length);
                UIColor* textColor = [self.weexInstance chooseColor:node.color darkThemeColor:node.darkThemeColor invert:invert scene:[self colorSceneType]];
                UIColor* bgColor = [self.weexInstance chooseColor:node.backgroundColor darkThemeColor:node.darkThemeBackgroundColor invert:invert scene:[self colorSceneType]];
                [attrStr addAttribute:NSForegroundColorAttributeName value:textColor ?: defaultTextColor range:range];
                [attrStr addAttribute:NSBackgroundColorAttributeName value:bgColor ?: defaultBackgroundColor range:range];
                
                UIFont *font = [WXUtility fontWithSize:node.fontSize textWeight:node.fontWeight textStyle:WXTextStyleNormal fontFamily:node.fontFamily scaleFactor:self.weexInstance.pixelScaleFactor];
                if (font) {
                    [attrStr addAttribute:NSFontAttributeName value:font range:range];
                }
                if (node.fontStyle == WXTextStyleItalic) {
                    [attrStr addAttribute:NSObliquenessAttributeName value:@0.3 range:range];
                }
                else
                {
                    [attrStr addAttribute:NSObliquenessAttributeName value:@0 range:range];
                }
                [attrStr addAttribute:NSUnderlineStyleAttributeName value:[NSNumber numberWithInteger:WXTextDecorationNone] range:range];
                [attrStr addAttribute:NSStrikethroughStyleAttributeName value:[NSNumber numberWithInteger:WXTextDecorationNone] range:range];
                
                if (node.textDecoration == WXTextDecorationUnderline) {
                    [attrStr addAttribute:NSUnderlineStyleAttributeName value:[NSNumber numberWithInteger:WXTextDecorationUnderline] range:range];
                }
                else if (node.textDecoration == WXTextDecorationLineThrough) {
                    [attrStr addAttribute:NSStrikethroughStyleAttributeName value:[NSNumber numberWithInteger:WXTextDecorationLineThrough] range:range];
                }
                
                if (node.href) {
                    [attrStr addAttribute:NSLinkAttributeName value:node.href range:range];
                }
                else {
                    [attrStr removeAttribute:NSLinkAttributeName range:range];
                }
                
                NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
                paragraphStyle.alignment = _textAlign;
                if(_lineHeight != 0 )
                {
                    paragraphStyle.minimumLineHeight = _lineHeight;
                    paragraphStyle.maximumLineHeight = _lineHeight;
                    [attrStr addAttribute:NSBaselineOffsetAttributeName value:@((_lineHeight - font.lineHeight)/2) range:range];
                }
                [attrStr addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:range];
                
                [nodeRange setObject:node forKey:NSStringFromRange(range)];
            }
        }
        else if ([node.type isEqualToString:@"image"]) {
            NSTextAttachment *imgAttachment = [[NSTextAttachment alloc]init];
            imgAttachment.bounds = CGRectMake(0, 0, node.width, node.height);
            
            NSAttributedString *attachAttriStr = [NSAttributedString attributedStringWithAttachment:imgAttachment];
            [attrStr appendAttributedString:attachAttriStr];
            
            NSRange range = NSMakeRange(location, attachAttriStr.length);
            [attrStr addAttribute:NSFontAttributeName value: [UIFont systemFontOfSize:node.height] range:range];
            
            if (node.href) {
                [attrStr addAttribute:NSLinkAttributeName value:node.href range:range];
            }
            else {
                [attrStr removeAttribute:NSLinkAttributeName range:range];
            }
            
            [nodeRange setObject:node forKey:NSStringFromRange(range)];
            
            if (node.src) {
                [[self imageLoader] downloadImageWithURL:node.src.absoluteString imageFrame:imgAttachment.bounds userInfo:nil completed:^(UIImage *image, NSError *error, BOOL finished) {
                    dispatch_async(dispatch_get_main_queue(), ^{
                        imgAttachment.image = image;
                        [[weakSelf textView].layoutManager invalidateDisplayForCharacterRange:range];
                    });
                }];
            }
        }
    }
    
    pthread_mutex_lock(&(_attributedStringMutex));
    [_nodeRanges removeAllObjects];
    _nodeRanges = [NSMutableDictionary dictionaryWithDictionary:nodeRange];
    pthread_mutex_unlock(&(_attributedStringMutex));
    
    return attrStr;
}

- (void)updateStyles:(NSDictionary *)styles {
    
    if (styles[@"textAlign"]) {
        _textAlign = [WXConvert NSTextAlignment:styles[@"textAlign"]];
    }
    if (styles[@"lineHeight"]) {
        _lineHeight = [WXConvert CGFloat:styles[@"lineHeight"]] / 2;
    }
    
    WXPerformBlockOnComponentThread(^{
        [_styles addEntriesFromDictionary:styles];
        [self syncTextStorageForView];
    });
}

- (void)updateChildNodeStyles:(NSDictionary *)styles ref:(NSString*)ref parentRef:(NSString*)parentRef {
    WXPerformBlockOnComponentThread(^{
        WXRichNode* node =  [self findRichNode:ref];
        if (node) {
            WXRichNode* superNode = [self findRichNode:@"_root"];
            if (parentRef.length > 0) {
                superNode = [self findRichNode:parentRef];
            }
            if (superNode) {
                [self fillCSSStyles:styles toNode:node superNode:superNode];
                [self syncTextStorageForView];
            }
        }
    });
}

- (void)updateAttributes:(NSDictionary *)attributes {
    WXPerformBlockOnComponentThread(^{
        _attributes = [NSMutableDictionary dictionaryWithDictionary:attributes];
        [self syncTextStorageForView];
    });
}

- (void)updateChildNodeAttributes:(NSDictionary *)attributes ref:(NSString*)ref parentRef:(NSString*)parentRef {
    WXPerformBlockOnComponentThread(^{
        WXRichNode* node =  [self findRichNode:ref];
        if (node) {
            WXRichNode* superNode = [self findRichNode:@"_root"];
            if (parentRef.length > 0) {
                superNode = [self findRichNode:parentRef];
            }
            if (superNode) {
                [self fillAttributes:attributes toNode:node superNode:superNode];
                [self syncTextStorageForView];
            }
        }
    });
}

- (void)syncTextStorageForView {
    pthread_mutex_lock(&(_attributedStringMutex));
    [self fillAttributes:_attributes];
    pthread_mutex_unlock(&(_attributedStringMutex));
    
    if (_styles[@"height"]) {
       [self innerLayout];
    }
    else {
       [self setNeedsLayout];
    }
}

#pragma mark - UITextView Delegate

- (BOOL)textView:(UITextView *)textView shouldInteractWithTextAttachment:(NSTextAttachment *)textAttachment inRange:(NSRange)characterRange {
    return NO;
}

- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange {
    if (!URL) {
        return NO;
    }
    
    NSString *rangeStr = NSStringFromRange(characterRange);
    WXRichNode *node = [_nodeRanges objectForKey:rangeStr];
    
    if (![[node.href absoluteString] isEqualToString:@"click://"]) {
        id<WXNavigationProtocol> navigationHandler = [self navigationHandler];
        if ([navigationHandler respondsToSelector:@selector(pushViewControllerWithParam:
                                                            completion:
                                                            withContainer:)]) {
            [navigationHandler pushViewControllerWithParam:@{@"url":URL.absoluteString} completion:^(NSString *code, NSDictionary *responseData) {
            } withContainer:self.weexInstance.viewController];
        } else {
            WXLogError(@"Event handler of class %@ does not respond to pushViewControllerWithParam", NSStringFromClass([navigationHandler class]));
        }
    }
    else if (node.pseudoRef) {
        NSMutableDictionary *params = [NSMutableDictionary new];
        [params setObject:node.pseudoRef forKey:@"pseudoRef"];
        [[WXSDKManager bridgeMgr] fireEvent:self.weexInstance.instanceId ref:self.ref type:@"itemclick" params:params domChanges:nil];
    }
    
    return NO;
}

# pragma mark - imageLoader

- (id<WXImgLoaderProtocol>)imageLoader {
    static id<WXImgLoaderProtocol> imageLoader;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        imageLoader = [WXSDKEngine handlerForProtocol:@protocol(WXImgLoaderProtocol)];
    });
    return imageLoader;
}

- (id<WXNavigationProtocol>)navigationHandler {
    static id<WXNavigationProtocol> navigationHandler;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        navigationHandler = [WXSDKEngine handlerForProtocol:@protocol(WXNavigationProtocol)];
    });
    return navigationHandler;
}

@end
