/*
 * 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 "WXTransform.h"
#import "math.h"
#import "WXLength.h"
#import "WXUtility.h"
#import "WXSDKInstance.h"
#import "WXConvert.h"
#import "WXSDKEngine.h"
#import "WXConfigCenterProtocol.h"

@interface WXTransform()

@property (nonatomic, weak) WXSDKInstance *weexInstance;

@end

@implementation WXTransform
{
    float _rotateAngle; //for rotate
    float _scaleX;
    float _scaleY;
    WXLength *_translateX;
    WXLength *_translateY;
    WXLength *_originX;
    WXLength *_originY;
    
    //3d rotate
    float _rotateX;
    float _rotateY;
    float _rotateZ;
    float _perspective;
    
    CATransform3D _nativeTransform;
    BOOL _useNativeTransform;
}

- (instancetype)initWithCSSValue:(NSString *)cssValue origin:(NSString *)origin instance:(WXSDKInstance *)instance
{
    if (self = [super init]) {
        _weexInstance = instance;
        _scaleX = 1.0;
        _scaleY = 1.0;
        _rotateX = 0.0;
        _rotateY = 0.0;
        _rotateZ = 0.0;
        _rotateAngle = 0.0;
        
        // default is parallel projection
        _perspective = CGFLOAT_MAX;
        
        [self parseTransform:cssValue];
        [self parseTransformOrigin:origin];
    }
    
    return self;
}

- (instancetype)initWithNativeTransform:(CATransform3D)transform instance:(WXSDKInstance *)instance
{
    if (self = [super init]) {
        _weexInstance = instance;
        _nativeTransform = transform;
        _useNativeTransform = YES;
    }
    return self;
}

- (float)rotateAngle
{
    if (_useNativeTransform) {
        return atan2(_nativeTransform.m11, _nativeTransform.m12);
    }
    return _rotateAngle;
}

- (float)rotateX
{
    if (_useNativeTransform) {
        return atan2(_nativeTransform.m22, _nativeTransform.m23);
    }
    return _rotateX;
}

- (float)rotateY
{
    if (_useNativeTransform) {
        return atan2(_nativeTransform.m11, _nativeTransform.m31);
    }
    return _rotateY;
}

- (float)rotateZ
{
    return _rotateZ;
}

- (WXLength *)translateX
{
    if (_useNativeTransform) {
        return [WXLength lengthWithFloat:_nativeTransform.m41 type:WXLengthTypeFixed];
    }
    return _translateX;
}

- (WXLength *)translateY
{
    if (_useNativeTransform) {
        return [WXLength lengthWithFloat:_nativeTransform.m42 type:WXLengthTypeFixed];
    }
    return _translateY;
}

- (float)scaleX
{
    if (_useNativeTransform) {
        return sqrt(_nativeTransform.m11 * _nativeTransform.m11 + _nativeTransform.m21 * _nativeTransform.m21);
    }
    return _scaleX;
}

- (float)scaleY
{
    if (_useNativeTransform) {
        return sqrt(_nativeTransform.m12 * _nativeTransform.m12 + _nativeTransform.m22 * _nativeTransform.m22);
    }
    return _scaleY;
}

- (void)setTransformOrigin:(NSString *)transformOriginCSS
{
    [self parseTransformOrigin:transformOriginCSS];
}

- (CATransform3D)nativeTransformWithView:(UIView *)view
{
    if (_useNativeTransform) {
        return _nativeTransform;
    }
    
    CATransform3D nativeTransform3d = [self nativeTransformWithoutRotateWithView:view];

    if (_rotateAngle != 0 || _rotateZ != 0) {
        nativeTransform3d = CATransform3DRotate(nativeTransform3d, _rotateAngle?:_rotateZ, 0, 0, 1);
    }
    
    if (_rotateY != 0) {
        nativeTransform3d = CATransform3DRotate(nativeTransform3d, _rotateY, 0, 1, 0);
    }
    
    if (_rotateX != 0) {
        nativeTransform3d = CATransform3DRotate(nativeTransform3d, _rotateX, 1, 0, 0);
    }
    
    return nativeTransform3d;
}

- (CATransform3D)nativeTransformWithoutRotateWithView:(UIView *)view
{
    CATransform3D nativeTansform3D = CATransform3DIdentity;
    
    // CGFLOAT_MAX is not INF on 32-bit device
    if(_perspective && _perspective != CGFLOAT_MAX && !isinf(_perspective)) { //!OCLint
        nativeTansform3D.m34 = -1.0/_perspective;
    }
    if (!view || view.bounds.size.width <= 0 || view.bounds.size.height <= 0) {
        return nativeTansform3D;
    }
    
    if (_translateX || _translateY) {
        
        nativeTansform3D = CATransform3DTranslate(nativeTansform3D, _translateX ? [_translateX valueForMaximum:view.bounds.size.width] : 0, _translateY ? [_translateY valueForMaximum:view.bounds.size.height]:0, 0);
    }
    nativeTansform3D = CATransform3DScale(nativeTansform3D, _scaleX, _scaleY, 1.0);
    
    return nativeTansform3D;
}

-(void)setAnchorPoint:(CGPoint)anchorPoint forView:(UIView *)view
{
    CGPoint newPoint = CGPointMake(view.bounds.size.width * anchorPoint.x,
                                   view.bounds.size.height * anchorPoint.y);
    CGPoint oldPoint = CGPointMake(view.bounds.size.width * view.layer.anchorPoint.x,
                                   view.bounds.size.height * view.layer.anchorPoint.y);
    
    newPoint = CGPointApplyAffineTransform(newPoint, view.transform);
    oldPoint = CGPointApplyAffineTransform(oldPoint, view.transform);
    
    CGPoint position = view.layer.position;
    
    position.x -= oldPoint.x;
    position.x += newPoint.x;
    
    position.y -= oldPoint.y;
    position.y += newPoint.y;
    
    view.layer.position = position;
    view.layer.anchorPoint = anchorPoint;
}


- (void)applyTransformForView:(UIView *)view
{
    if (!view || view.bounds.size.width <= 0 || view.bounds.size.height <= 0) {
        return;
    }
    
    BOOL applyTransformOrigin = _originX || _originY;
    if (applyTransformOrigin) {
        /**
          * Waiting to fix the issue that transform-origin behaves in rotation
          * http://ronnqvi.st/translate-rotate-translate/
          **/
        CGPoint anchorPoint = CGPointMake(
                                          _originX ? [_originX valueForMaximum:view.bounds.size.width] / view.bounds.size.width : 0.5,
                                          _originY ? [_originY valueForMaximum:view.bounds.size.height] / view.bounds.size.height : 0.5);
        [self setAnchorPoint:anchorPoint forView:view];
    }
    CATransform3D nativeTransform3d = [self nativeTransformWithView:view];
    if (!CATransform3DEqualToTransform(view.layer.transform, nativeTransform3d)){
        view.layer.transform = nativeTransform3d;
    }
}

- (void)parseTransform:(NSString *)cssValue
{
    if (!cssValue || cssValue.length == 0 || [cssValue isEqualToString:@"none"]) {
        return;
    }
    
    static NSRegularExpression* parseRegex = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        NSError *error = NULL;
        parseRegex = [NSRegularExpression regularExpressionWithPattern:@"(\\w+)\\((.+?)\\)"
                                                               options:NSRegularExpressionCaseInsensitive
                                                                 error:&error];
    });
    
    NSArray *matches = [parseRegex matchesInString:cssValue options:0 range:NSMakeRange(0, cssValue.length)];
    
    for (NSTextCheckingResult *match in matches) {
        NSString *name = [cssValue substringWithRange:[match rangeAtIndex:1]];
        NSArray *value = [[cssValue substringWithRange:[match rangeAtIndex:2]] componentsSeparatedByString:@","];
        
        SEL method = NSSelectorFromString([NSString stringWithFormat:@"parse%@:", [name capitalizedString]]);
        if ([self respondsToSelector:method]) {
            @try {
                IMP imp = [self methodForSelector:method];
                void (*func)(id, SEL,NSArray *) = (void *)imp;
                func(self, method,value);
            }
            @catch (NSException *exception) {
                WXLogError(@"WXTransform exception:%@", [exception reason]);
            }
        }
    }
}

- (void)parseTransformOrigin:(NSString *)cssValue
{
    if (!cssValue || cssValue.length == 0 || [cssValue isEqualToString:@"none"]) {
        return;
    }
    
    NSArray *values = [cssValue componentsSeparatedByString:@" "];

    double originX = 50;
    double originY = 50;
    WXLengthType typeX = WXLengthTypePercent;
    WXLengthType typeY = WXLengthTypePercent;
    for (NSInteger i = 0; i < values.count; i++) {
        NSString *value = values[i];
        if ([value isEqualToString:@"left"]) {
            originX = 0;
        } else if ([value isEqualToString:@"right"]) {
            originX = 100;
        } else if ([value isEqualToString:@"top"]) {
            originY = 0;
        } else if ([value isEqualToString:@"bottom"]) {
            originY = 100;
        } else if ([value isEqualToString:@"center"]) {
            if (i == 0) {
                originX = 50;
            } else {
                originY = 50;
            }
        } else {
            double val = [value doubleValue];
            if (i == 0) {
                if ([value hasSuffix:@"%"]) {
                    originX = val;
                } else {
                    typeX = WXLengthTypeFixed;
                    originX = WXPixelScale(val, self.weexInstance.pixelScaleFactor);
                }
            } else {
                if ([value hasSuffix:@"%"]) {
                    originY = val;
                } else {
                    typeY = WXLengthTypeFixed;
                    originY = WXPixelScale(val, self.weexInstance.pixelScaleFactor);
                }
            }
        }
    }
    _originX = [WXLength lengthWithFloat:originX type:typeX];
    _originY = [WXLength lengthWithFloat:originY type:typeY];
}

- (void)parseRotate:(NSArray *)value
{
    float rotateAngle = [self getAngle:value[0]];
    _rotateAngle = rotateAngle;
}

- (void)parseRotatex:(NSArray *)value
{
    _rotateX = [self getAngle:value[0]];
}

- (void)parseRotatey:(NSArray *)value
{
    _rotateY = [self getAngle:value[0]];
}

- (void)parseRotatez:(NSArray *)value
{
   _rotateZ = [self getAngle:value[0]];
}

- (void)parsePerspective:(NSArray *)value
{
    _perspective = [WXConvert WXPixelType:value[0] scaleFactor:self.weexInstance.pixelScaleFactor];
    if (_perspective <= 0 ) {
        _perspective = CGFLOAT_MAX;
    }
}

- (void)parseTranslate:(NSArray *)value
{
    [self parseTranslatex:@[value[0]]];
    if (value.count > 1) {
        [self parseTranslatey:@[value[1]]];
    }
}

- (void)parseTranslatex:(NSArray *)value
{
    WXLength *translateX;
    double x = [value[0] doubleValue];
    if ([value[0] hasSuffix:@"%"]) {
        translateX = [WXLength lengthWithFloat:x type:WXLengthTypePercent];
    } else {
        x = [WXConvert WXPixelType:value[0] scaleFactor:self.weexInstance.pixelScaleFactor];
        translateX = [WXLength lengthWithFloat:x type:WXLengthTypeFixed];
    }
    _translateX = translateX;
}

- (void)parseTranslatey:(NSArray *)value
{
    WXLength *translateY;
    double y = [value[0] doubleValue];
    if ([value[0] hasSuffix:@"%"]) {
        translateY = [WXLength lengthWithFloat:y type:WXLengthTypePercent];
    } else {
        y = [WXConvert WXPixelType:value[0] scaleFactor:self.weexInstance.pixelScaleFactor];
        translateY = [WXLength lengthWithFloat:y type:WXLengthTypeFixed];
    }
    _translateY = translateY;
}

- (void)parseScale:(NSArray *)value
{
    double x = [value[0] doubleValue];
    double y = x;
    if (value.count == 2) {
        y = [value[1] doubleValue];
    }
    _scaleX = x;
    _scaleY = y;
}

- (void)parseScalex:(NSArray *)value
{
	_scaleX = [value[0] doubleValue];
}

- (void)parseScaley:(NSArray *)value
{
	_scaleY = [value[0] doubleValue];
}

// Angle in radians
- (double)getAngle:(NSString *)value
{
    double angle = [value doubleValue];
    if ([value hasSuffix:@"deg"]) {
        return [self deg2rad:angle];
    } else {
        return angle;
    }
}

- (double)deg2rad:(double)deg
{
    return deg * M_PI / 180.0;
}

@end
