/*
 * 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 "WXAnimationModule.h"
#import "WXSDKInstance_private.h"
#import "WXComponent_internal.h"
#import "WXConvert.h"
#import "WXTransform.h"
#import "WXUtility.h"
#import "WXLength.h"
#import "WXTransition.h"
#import "WXComponent+Layout.h"
#import "WXDarkThemeProtocol.h"

@interface WXAnimationInfo : NSObject<NSCopying>

@property (nonatomic, weak) WXComponent *target;
@property (nonatomic, strong) NSString *propertyName;
@property (nonatomic, strong) id fromValue;
@property (nonatomic, strong) id toValue;
@property (nonatomic, assign) double duration;
@property (nonatomic, assign) double delay;
@property (nonatomic, strong) CAMediaTimingFunction *timingFunction;
@property (nonatomic, assign) CGPoint originAnchorPoint;
@end

@implementation WXAnimationInfo

- (id)copyWithZone:(NSZone *)zone
{
    WXAnimationInfo *info = [[WXAnimationInfo allocWithZone:zone] init];
    info.target = self.target;
    info.propertyName = self.propertyName;
    info.fromValue = self.fromValue;
    info.toValue = self.toValue;
    info.duration = self.duration;
    info.delay = self.delay;
    info.timingFunction = self.timingFunction;
    return info;
}

@end

#if __IPHONE_OS_VERSION_MAX_ALLOWED < 100000
// CAAnimationDelegate is not available before iOS 10 SDK
@interface WXAnimationDelegate : NSObject 
#else
@interface WXAnimationDelegate : NSObject <CAAnimationDelegate>
#endif

@property (nonatomic, copy) void (^finishBlock)(BOOL);
@property (nonatomic, strong) WXAnimationInfo *animationInfo;

- (instancetype)initWithAnimationInfo:(WXAnimationInfo *)info finishBlock:(void(^)(BOOL))finishBlock;

@end

@implementation WXAnimationDelegate

- (instancetype)initWithAnimationInfo:(WXAnimationInfo *)info finishBlock:(void (^)(BOOL))finishBlock
{
    if (self = [super init]) {
        _animationInfo = info;
        _finishBlock = finishBlock;
    }
    return self;
}

- (void)animationDidStart:(CAAnimation *)anim
{
    [self applyTransform];
}

-(void)applyTransform
{
    if (!_animationInfo.target || ![_animationInfo.target isViewLoaded]) {
        return;
    }
    if ([_animationInfo.propertyName hasPrefix:@"transform"]) {
        WXTransform *transform = _animationInfo.target->_transform;
        [transform applyTransformForView:_animationInfo.target.view];
        [_animationInfo.target _adjustForRTL];
    } else if ([_animationInfo.propertyName isEqualToString:@"backgroundColor"]) {
        _animationInfo.target.view.layer.backgroundColor = (__bridge CGColorRef _Nullable)(_animationInfo.toValue);
    } else if ([_animationInfo.propertyName isEqualToString:@"opacity"]) {
        _animationInfo.target.view.layer.opacity = [_animationInfo.toValue floatValue];
    } else if ([_animationInfo.propertyName hasPrefix:@"bounds.size"]) {
        CGRect newBounds = _animationInfo.target.view.layer.bounds;
        if ([_animationInfo.propertyName isEqualToString:@"bounds.size.width"]) {
            newBounds.size = CGSizeMake([_animationInfo.toValue floatValue], newBounds.size.height);
        }else if ([_animationInfo.propertyName isEqualToString:@"bounds.size.height"]) {
            newBounds.size = CGSizeMake(newBounds.size.width,[_animationInfo.toValue floatValue]);
        }
        _animationInfo.target.view.layer.bounds = newBounds;
    }
}

- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
{
    if (!_animationInfo.target) {
        return;
    }
    
    if ([_animationInfo.propertyName hasPrefix:@"bounds.size"]) {
        /*
         * http://ronnqvi.st/about-the-anchorpoint/
         */
        //
        CGRect originFrame = _animationInfo.target.view.layer.frame;
        _animationInfo.target.view.layer.anchorPoint = _animationInfo.originAnchorPoint;
        _animationInfo.target.view.layer.frame = originFrame;
    }
    [_animationInfo.target.layer removeAnimationForKey:_animationInfo.propertyName];
    
    if (_finishBlock) {
        _finishBlock(flag);
    }
}

@end

@interface WXAnimationModule ()

@property (nonatomic, assign) BOOL isAnimationedSuccess;

@end

@implementation WXAnimationModule

@synthesize weexInstance;

WX_EXPORT_METHOD(@selector(transition:args:callback:))

- (void)transition:(NSString *)nodeRef args:(NSDictionary *)args callback:(WXModuleKeepAliveCallback)callback
{
    _isAnimationedSuccess = YES;
    WXPerformBlockOnComponentThread(^{
        if (nodeRef == nil || ![nodeRef isKindOfClass:[NSString class]] ||
            ![args isKindOfClass:[NSDictionary class]]) {
            if (callback) {
                NSDictionary *message = @{@"result":@"Fail",
                                          @"message":@"Argument type error."};
                callback(message, NO);
            }
            return;
        }
        
        NSArray *stringArray = [nodeRef componentsSeparatedByString:@"@"];
        if ([stringArray count] == 0) {
            if (callback) {
                NSDictionary *message = @{@"result":@"Fail",
                                          @"message":@"Node ref format error."};
                callback(message, NO);
            }
            return;
        }
        
        WXComponent *targetComponent = [self.weexInstance componentForRef:stringArray[0]];
        if (!targetComponent) {
            if (callback) {
                NSDictionary *message = @{@"result":@"Fail",
                                          @"message":[NSString stringWithFormat:@"No component find for ref:%@", nodeRef]};
                callback(message, NO);
            }
            return;
        }
        WXPerformBlockOnMainThread(^{
            [self animation:targetComponent args:args callback:callback];
        });
    });
}

- (NSArray<WXAnimationInfo *> *)animationInfoArrayFromArgs:(NSDictionary *)args target:(WXComponent *)target
                                                needLayout:(BOOL* _Nonnull)needLayout
                                                transition:(WXTransition* _Nonnull *)transition
                                             transitionDic:(NSMutableDictionary* _Nonnull *)transitionDic
{
    UIView *view = target.view;
    CALayer *layer = target.layer;
    NSMutableArray<WXAnimationInfo *> *infos = [NSMutableArray new];

    double duration = [args[@"duration"] doubleValue] / 1000;
    double delay = [args[@"delay"] doubleValue] / 1000;
    if (args[@"needLayout"]) {
        *needLayout = [WXConvert BOOL:args[@"needLayout"]];
        if (*needLayout) {
            *transition = [WXTransition new];
            *transitionDic = [NSMutableDictionary new];
            (*transition).filterStyles = [NSMutableDictionary new];
            (*transition).oldFilterStyles = [NSMutableDictionary new];
        }
    }
    CAMediaTimingFunction *timingFunction = [WXConvert CAMediaTimingFunction:args[@"timingFunction"]];
    NSDictionary *styles = args[@"styles"];
    NSDictionary* componentRawStyles = target.styles;
    
    BOOL isDarkTheme = [target.weexInstance isDarkTheme];
    BOOL updatingDarkThemeBackgroundColor = styles[@"darkThemeBackgroundColor"] != nil;
    
    for (NSString *property in styles) {
        if ([property isEqualToString:@"backgroundColor"]) {
            if (isDarkTheme && (updatingDarkThemeBackgroundColor ||
                                componentRawStyles[@"darkThemeBackgroundColor"] != nil)) {
                /* Updating "darkThemeBackgroundColor" in dark mode,
                 or this component has dark bg color explicitly defined in styels.
                 We ignore transition animation for "backgroundColor" */
                continue;
            }
        }
        else if ([property isEqualToString:@"darkThemeBackgroundColor"]) {
            if (!isDarkTheme || componentRawStyles[@"darkThemeBackgroundColor"] == nil) {
                /* Do not do animation for "darkThemeBackgroundColor" in light mode.
                 Or there is no dark bg color explicitly defined in styles.
                 */
                continue;
            }
        }
        
        WXAnimationInfo *info = [WXAnimationInfo new];
        info.duration = duration;
        info.delay = delay;
        info.timingFunction = timingFunction;
        info.target = target;
        
        id value = styles[property];
        if ([property isEqualToString:@"transform"]) {
            NSString *transformOrigin = styles[@"transformOrigin"];
            WXTransform *wxTransform = [[WXTransform alloc] initWithCSSValue:value origin:transformOrigin instance:self.weexInstance];
            WXTransform *oldTransform = target->_transform;
            if (wxTransform.rotateAngle != oldTransform.rotateAngle) {
                WXAnimationInfo *newInfo = [info copy];
                newInfo.propertyName = @"transform.rotation";
                /**
                 Rotate >= 180 degree not working on UIView block animation, have not found any more elegant solution than using CAAnimation
                 See http://stackoverflow.com/questions/9844925/uiview-infinite-360-degree-rotation-animation
                 **/
                newInfo.fromValue = @(oldTransform.rotateAngle);
                newInfo.toValue = [NSNumber numberWithDouble:wxTransform.rotateAngle];
                [infos addObject:newInfo];
            }
            if (wxTransform.rotateX != oldTransform.rotateX)
            {
                WXAnimationInfo *newInfo = [info copy];
                newInfo.propertyName = @"transform.rotation.x";
                newInfo.fromValue = @(oldTransform.rotateX);
                newInfo.toValue = [NSNumber numberWithDouble:wxTransform.rotateX];
                 [infos addObject:newInfo];
            }
            if (wxTransform.rotateY != oldTransform.rotateY)
            {
                WXAnimationInfo *newInfo = [info copy];
                newInfo.propertyName = @"transform.rotation.y";
                newInfo.fromValue = @(oldTransform.rotateY);
                newInfo.toValue = [NSNumber numberWithDouble:wxTransform.rotateY];
                [infos addObject:newInfo];
            }
            if (wxTransform.rotateZ != oldTransform.rotateZ)
            {
                WXAnimationInfo *newInfo = [info copy];
                newInfo.propertyName = @"transform.rotation.z";
                newInfo.fromValue = @(oldTransform.rotateZ);
                newInfo.toValue = [NSNumber numberWithDouble:wxTransform.rotateZ];
                [infos addObject:newInfo];
            }
            
            if (wxTransform.scaleX != oldTransform.scaleX) {
                WXAnimationInfo *newInfo = [info copy];
                newInfo.propertyName = @"transform.scale.x";
                newInfo.fromValue = @(oldTransform.scaleX);
                newInfo.toValue = @(wxTransform.scaleX);
                [infos addObject:newInfo];
            }
            
            if (wxTransform.scaleY != oldTransform.scaleY) {
                WXAnimationInfo *newInfo = [info copy];
                newInfo.propertyName = @"transform.scale.y";
                newInfo.fromValue = @(oldTransform.scaleY);
                newInfo.toValue = @(wxTransform.scaleY);
                [infos addObject:newInfo];
            }
            
            if ((wxTransform.translateX && ![wxTransform.translateX isEqualToLength:oldTransform.translateX]) || (!wxTransform.translateX && oldTransform.translateX)) {
                WXAnimationInfo *newInfo = [info copy];
                newInfo.propertyName = @"transform.translation.x";
                newInfo.fromValue = @([oldTransform.translateX valueForMaximum:view.bounds.size.width]);
                newInfo.toValue = @([wxTransform.translateX valueForMaximum:view.bounds.size.width]);
                [infos addObject:newInfo];
            }
            
            if ((wxTransform.translateY && ![wxTransform.translateY isEqualToLength:oldTransform.translateY]) || (!wxTransform.translateY && oldTransform.translateY)) {
                WXAnimationInfo *newInfo = [info copy];
                newInfo.propertyName = @"transform.translation.y";
                newInfo.fromValue = @([oldTransform.translateY valueForMaximum:view.bounds.size.height]);
                newInfo.toValue = @([wxTransform.translateY valueForMaximum:view.bounds.size.height]);
                [infos addObject:newInfo];
            }
            target.transform = wxTransform;
        } else if ([property isEqualToString:@"backgroundColor"] ||
                   [property isEqualToString:@"darkThemeBackgroundColor"]) {
            info.propertyName = @"backgroundColor";
            info.fromValue = (__bridge id)(layer.backgroundColor);
            UIColor* toColor = [WXConvert UIColor:value];
            if ([target.weexInstance isDarkTheme] && target.invertForDarkTheme &&
                [property isEqualToString:@"backgroundColor"]) {
                // Invert color
                toColor = [[WXSDKInstance darkThemeColorHandler] getInvertedColorFor:toColor ofScene:[target colorSceneType] withDefault:toColor];
            }
            info.toValue = (__bridge id)([toColor CGColor]);
            [infos addObject:info];
        } else if ([property isEqualToString:@"opacity"]) {
            info.propertyName = @"opacity";
            info.fromValue = @(layer.opacity);
            info.toValue = @([value floatValue]);
            [infos addObject:info];
        } else if ([property isEqualToString:@"width"]) {
            if (*needLayout) {
                [self transitionWithArgs:args withProperty:property target:target transition:*transition transitionDic:*transitionDic];
            }
            else
            {
                info.propertyName = @"bounds.size.width";
                info.fromValue = @(layer.bounds.size.width);
                CGRect newBounds = layer.bounds;
                newBounds.size = CGSizeMake([WXConvert WXPixelType:value scaleFactor:self.weexInstance.pixelScaleFactor], newBounds.size.height);
                info.toValue = @(newBounds.size.width);
                [infos addObject:info];
            }
        } else if ([property isEqualToString:@"height"]) {
            if (*needLayout) {
                [self transitionWithArgs:args withProperty:property target:target transition:*transition transitionDic:*transitionDic];
            }
            else
            {
                info.propertyName = @"bounds.size.height";
                info.fromValue = @(layer.bounds.size.height);
                CGRect newBounds = layer.bounds;
                newBounds.size = CGSizeMake(newBounds.size.width, [WXConvert WXPixelType:value scaleFactor:self.weexInstance.pixelScaleFactor]);
                info.toValue = @(newBounds.size.height);
                [infos addObject:info];
            }
        }
    }
    return infos;
}

- (void)transitionWithArgs:(NSDictionary *)args withProperty:(NSString *)property target:(WXComponent *)target
                transition:(WXTransition*)transition
             transitionDic:(NSMutableDictionary*)transitionDic
{
    if (args[@"styles"][property] == nil) {
        return;
    }
    
    [transition.filterStyles setObject:args[@"styles"][property] forKey:property];
    
    id oldStyleValue = target.styles[property];
    if (oldStyleValue == nil) {
        oldStyleValue = [target convertLayoutValueToStyleValue:property];
    }
    if (oldStyleValue == nil) {
        oldStyleValue = @"0.0";
    }
    [transition.oldFilterStyles setObject:oldStyleValue ?:@0 forKey:property];
    
    [target _modifyStyles:@{property:args[@"styles"][property]}];
    [transitionDic setObject:@([args[@"duration"] doubleValue]) forKey:kWXTransitionDuration];
    [transitionDic setObject:@([args[@"delay"] doubleValue]) forKey:kWXTransitionDelay];
    [transitionDic setObject:args[@"timingFunction"] ?: @"linear" forKey:kWXTransitionTimingFunction];
}

- (void)animation:(WXComponent *)targetComponent args:(NSDictionary *)args callback:(WXModuleKeepAliveCallback)callback
{
    /* Check if view of targetComponent is created, if not, we do not do animation and
     simulate delay of 'duration' and callback.
     For a view in list, the view migth be recycled, and if view is not attached to a window,
     the CATransaction completion block will be called immediately, which may cause CPU overload
     problem if JS code do any logic in the completion callback.
     */
    
    BOOL shouldDoAnimation = NO;
    if ([targetComponent isViewLoaded]) {
        UIView* view = targetComponent.view;
        if ([view window] != nil) {
            shouldDoAnimation = YES;
        }
    }
    
    /**
       UIView-style animation functions support the standard timing functions,
       but they don’t allow you to specify your own cubic Bézier curve. 
       CATransaction can be used instead to force these animations to use the supplied CAMediaTimingFunction to pace animations.
     **/
    [CATransaction begin];
    [CATransaction setAnimationTimingFunction:[WXConvert CAMediaTimingFunction:args[@"timingFunction"]]];
    
    if (shouldDoAnimation) {
        [CATransaction setCompletionBlock:^{
            if (callback) {
                NSDictionary *message;
                if (_isAnimationedSuccess) {
                    message = @{@"result":@"Success",
                                @"message":@"Success"};
                }
                else
                {
                    message = @{@"result":@"Fail",
                                @"message":@"Animation did not complete"};
                }
                callback(message, NO);
            }
        }];
    }
    else if (callback) {
        double duration = [[args objectForKey:@"duration"] doubleValue] / 1000.f;
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(duration * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            callback(@{@"result":@"Success",
                       @"message":@"Success"}, NO);
        });
    }
    
    BOOL needLayout = NO;
    WXTransition* transition = nil;
    NSMutableDictionary* transitionDic = nil;
    NSArray<WXAnimationInfo *> *infos = [self animationInfoArrayFromArgs:args target:targetComponent needLayout:&needLayout transition:&transition transitionDic:&transitionDic];
    for (WXAnimationInfo *info in infos) {
        [self _createCAAnimation:info];
    }
    
    [CATransaction commit];
    
    if (needLayout && transition) {
        WXPerformBlockOnComponentThread(^{
            [transition _handleTransitionWithStyles:transitionDic resetStyles:nil target:targetComponent];
        });
    }
}

- (void)_createCAAnimation:(WXAnimationInfo *)info
{
    CABasicAnimation* animation = [CABasicAnimation animationWithKeyPath:info.propertyName];
    animation.fromValue = info.fromValue;
    animation.toValue = info.toValue;
    animation.duration = info.duration;
    animation.beginTime = CACurrentMediaTime() + info.delay;
    animation.timingFunction = info.timingFunction;
    animation.removedOnCompletion = NO;
    animation.fillMode = kCAFillModeForwards;
    
    WXAnimationDelegate *delegate = [[WXAnimationDelegate alloc] initWithAnimationInfo:info finishBlock:^(BOOL isFinish) {
        if (!isFinish) {
            _isAnimationedSuccess = isFinish;
        }
    }];
    animation.delegate = delegate;
    
    CALayer *layer = info.target.layer;
    if ([info.propertyName hasPrefix:@"bounds"]) {
        info.originAnchorPoint = layer.anchorPoint;
        CGRect originFrame = layer.frame;
         /*
          * if anchorPoint changed, the origin of layer's frame will change
          * http://ronnqvi.st/about-the-anchorpoint/
         */
        layer.anchorPoint = CGPointZero;
        layer.frame = originFrame;
    }
    
    if(!WXFloatGreaterThan(animation.duration, 0)){
        if([delegate respondsToSelector:@selector(applyTransform)]) {
            [delegate applyTransform];
        }
    } else {
        CATransform3D transform = layer.transform;
        if (info.target->_transform.perspective && !isinf(info.target->_transform.perspective)) { //!OCLint
            transform.m34 = -1.0/info.target->_transform.perspective*[UIScreen mainScreen].scale;
            layer.transform = transform;
        }
        [layer addAnimation:animation forKey:info.propertyName];
    }
}

@end
