//
//  PDFSignatureDrawView.m
//  PDFReader
//
//  Copyright © 2014-2022 PDF Technologies, Inc. All Rights Reserved.
//
//  The PDF Reader Sample applications are licensed with a modified BSD license.
//  Please see License for details. This notice may not be removed from this file.
//

#import "PDFSignatureDrawView.h"

static CGPoint _points[5];
static NSInteger _index;

@interface PDFSignatureDrawView ()

@property (nonatomic,retain) UIBezierPath *bezierPath;

@end

@implementation PDFSignatureDrawView

#pragma mark - Init Methods

- (instancetype)initWithFrame:(CGRect)frame {
    if (self = [super initWithFrame:frame]) {
        _bezierPath = [[UIBezierPath alloc] init];
        _color = [[UIColor blackColor] retain];
        _lineWidth = 5;
    }
    return self;
}

- (instancetype)initWithCoder:(NSCoder *)aDecoder {
    if (self = [super initWithCoder:aDecoder]) {
        _bezierPath = [[UIBezierPath alloc] init];
        _color = [[UIColor blackColor] retain];
        _lineWidth = 5;
    }
    return self;
}

- (void)dealloc {
    [_image release];
    [_color release];
    [_bezierPath release];
    [super dealloc];
}

#pragma mark - Draw Methods

- (void)layoutSubviews {
    [super layoutSubviews];
    [self setNeedsDisplay];
}

- (void)drawRect:(CGRect)rect {
    [super drawRect:rect];
    
    if (self.image) {
        CGRect imageFrame = [self imageFrameInRect:rect];
        [self.image drawInRect:imageFrame];
    }
    
    [self.color set];
    [self.bezierPath setLineWidth:self.lineWidth];
    [self.bezierPath setLineCapStyle:kCGLineCapRound];
    [self.bezierPath setLineJoinStyle:kCGLineJoinRound];
    [self.bezierPath stroke];
}

- (CGRect)imageFrameInRect:(CGRect)rect {
    CGRect imageRect;
    if (self.image.size.width < rect.size.width &&
        self.image.size.height < rect.size.height) {
        imageRect.origin.x = (rect.size.width-self.image.size.width)/2.0;
        imageRect.origin.y = (rect.size.height-self.image.size.height)/2.0;
        imageRect.size = self.image.size;
    } else {
        if (self.image.size.width/self.image.size.height >
            rect.size.width/rect.size.height) {
            imageRect.size.width = rect.size.width;
            imageRect.size.height = rect.size.width*self.image.size.height/self.image.size.width;
        } else {
            imageRect.size.height = rect.size.height;
            imageRect.size.width = rect.size.height*self.image.size.width/self.image.size.height;
        }
        imageRect.origin.x = (rect.size.width-imageRect.size.width)/2.0;
        imageRect.origin.y = (rect.size.height-imageRect.size.height)/2.0;
    }
    return imageRect;
}

#pragma mark - Public Mehtods

- (UIImage *)signatureImage {
    CGRect rect = CGRectZero;
    CGRect imageFrame = [self imageFrameInRect:self.frame];
    if (self.image) {
        if (self.bezierPath.empty) {
            rect = imageFrame;
        } else {
            CGRect pathFrame = self.bezierPath.bounds;
            rect.origin.x = MIN(CGRectGetMinX(imageFrame), CGRectGetMinX(pathFrame));
            rect.origin.y = MIN(CGRectGetMinY(imageFrame), CGRectGetMinY(pathFrame));
            rect.size.width = MAX(CGRectGetMaxX(imageFrame), CGRectGetMaxX(pathFrame))-rect.origin.x;
            rect.size.height = MAX(CGRectGetMaxY(imageFrame), CGRectGetMaxY(pathFrame))-rect.origin.y;
        }
    } else {
        if (self.bezierPath.empty) {
            return nil;
        } else {
            rect = self.bezierPath.bounds;
        }
    }
    
    CGSize size = CGSizeMake(rect.size.width+self.bezierPath.lineWidth,
                             rect.size.height+self.bezierPath.lineWidth);
    UIGraphicsBeginImageContext(size);
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGAffineTransform transform = CGAffineTransformMakeTranslation(-rect.origin.x+self.bezierPath.lineWidth/2.0,  -rect.origin.y+self.bezierPath.lineWidth/2.0);
    CGContextConcatCTM(context, transform);
    if (self.image) {
        [self.image drawInRect:imageFrame];
    }
    if (!self.bezierPath.empty) {
        CGContextSetStrokeColorWithColor(context, self.color.CGColor);
        CGContextSetLineWidth(context, self.bezierPath.lineWidth);
        CGContextSetLineCap(context, self.bezierPath.lineCapStyle);
        CGContextSetLineJoin(context, self.bezierPath.lineJoinStyle);
        CGContextAddPath(context, self.bezierPath.CGPath);
        CGContextStrokePath(context);
    }
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return image;
}

- (void)clear {
    self.image = nil;
    [self.bezierPath removeAllPoints];
    [self setNeedsDisplay];
}

- (void)setColor:(UIColor *)color {
    if (_color != color) {
        [_color release];
        _color = [color retain];
    }
    [self setNeedsDisplay];
}

- (void)setLineWidth:(CGFloat)lineWidth {
    _lineWidth = lineWidth;
    [self setNeedsDisplay];
}

- (void)setImage:(UIImage *)image {
    if (_image != image) {
        [_image release];
        _image = [image retain];
    }
    [self setNeedsDisplay];
}

#pragma mark - Touch Methods

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    [super touchesBegan:touches withEvent:event];
    CGPoint point = [[touches anyObject] locationInView:self];
    _index = 0;
    _points[0] = point;
}

- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    [super touchesMoved:touches withEvent:event];
    CGPoint point = [[touches anyObject] locationInView:self];
    _index++;
    _points[_index] = point;
    if (_index == 4) {
        _points[3] = CGPointMake((_points[2].x + _points[4].x)/2.0,
                                 (_points[2].y + _points[4].y)/2.0);
        [self.bezierPath moveToPoint:_points[0]];
        [self.bezierPath addCurveToPoint:_points[3]
                           controlPoint1:_points[1]
                           controlPoint2:_points[2]];
        _points[0] = _points[3];
        _points[1] = _points[4];
        _index = 1;
        [self setNeedsDisplay];
    }
}

- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    [super touchesEnded:touches withEvent:event];
    if (_index < 4) {
        for (int i=0; i<_index; i++) {
            [self.bezierPath moveToPoint:_points[i]];
        }
        [self setNeedsDisplay];
    }
}

@end