//
//  AvatarGenerator.h
//  rainbow
//
//  Created by Doha Tubaileh on 6/14/20.
//  Copyright © 2020 Facebook. All rights reserved.
//


#import "AvatarGenerator.h"
#import <Rainbow/Rainbow.h>
#import "Contact+DictRepresentation.h"
#import "UIColor+ImageWithColorCreator.h"


@implementation AvatarGenerator




+(UIImage *) cropImage:(UIImage *) image withRect:(CGRect) croprect {
    // The scale parameter might not be used here, but it works so...
    CGImageRef imageRef = CGImageCreateWithImageInRect([image CGImage], CGRectMake(croprect.origin.x * image.scale,
                                                                                   croprect.origin.y * image.scale,
                                                                                   croprect.size.width * image.scale,
                                                                                   croprect.size.height * image.scale));
    UIImage *croppedImage = [UIImage imageWithCGImage:imageRef];
    CGImageRelease(imageRef);
    return croppedImage;
}

+(UIImage *) setPhotoForPeer:(Peer *) peer {
    if ([peer isKindOfClass:[Contact class]]) {
        Contact *contact = (Contact *) peer;
        return contact.getContactImage;
        
    } else if ([peer isKindOfClass:[Room class]]) {
        
        Room *room = (Room *)peer;
        
        // If defined, display the custom avatar
        if( room.photoData != nil ) {
            UIImage *image = [[UIImage alloc] initWithData:room.photoData];
            return image;
        }
        
        // Build the avatar only with the accepted participants only if it's not my room else use all participants list
        NSMutableOrderedSet<Participant *> *participantsToDisplay = nil;
        
        if(room.isMyRoom){
            participantsToDisplay = [NSMutableOrderedSet orderedSetWithArray:[[room participants] filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(Participant *evaluatedObject, NSDictionary<NSString *,id> * bindings) {
                return (evaluatedObject.status != ParticipantStatusUnsubscribed) && (evaluatedObject.status != ParticipantStatusDeleted) && (evaluatedObject.status != ParticipantStatusRejected);
            }]]];
            
            Participant *myParticipant = [room participantFromContact:[ServicesManager sharedInstance].myUser.contact];
            
            
            if(myParticipant && ![participantsToDisplay containsObject:myParticipant]){
                // Not in participant list add myself in this list
                [participantsToDisplay insertObject:myParticipant atIndex:0];
            }
            
        }
        else {
            participantsToDisplay = [NSMutableOrderedSet orderedSetWithArray:[[room participants] filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(Participant *evaluatedObject, NSDictionary<NSString *,id> * bindings) {
                if ((evaluatedObject.status == ParticipantStatusUnsubscribed) && (evaluatedObject.privilege == ParticipantPrivilegeOwner)) {
                    return (evaluatedObject.status == ParticipantStatusUnsubscribed) && (evaluatedObject.privilege == ParticipantPrivilegeOwner);
                }
                
                return (evaluatedObject.status != ParticipantStatusUnsubscribed) && (evaluatedObject.status != ParticipantStatusDeleted) && (evaluatedObject.status != ParticipantStatusRejected);
            }]]];
            
            for (Participant * aParticipant in participantsToDisplay) {
                if (aParticipant.privilege == ParticipantPrivilegeOwner && aParticipant.status == ParticipantStatusUnsubscribed) {
                    [participantsToDisplay removeAllObjects];
                    [participantsToDisplay addObject:aParticipant];
                    break;
                }
            }
        }
        
        [participantsToDisplay sortUsingComparator:^NSComparisonResult(Participant *obj1, Participant *obj2) {
            if([obj1.addedDate isLaterThanDate:obj2.addedDate])
                return NSOrderedDescending;
            return NSOrderedAscending;
        }];
        
        // If the first participant to display is not the owner, loop to find him and place at the first place
        if (participantsToDisplay.firstObject && participantsToDisplay.firstObject.privilege != ParticipantPrivilegeOwner) {
            for (Participant * aParticipant in participantsToDisplay) {
                if (aParticipant.privilege == ParticipantPrivilegeOwner) {
                    [participantsToDisplay removeObject:aParticipant];
                    [participantsToDisplay insertObject:aParticipant atIndex:0];
                    break;
                }
            }
        }
        
        // Save generated avatar from participants list in cache
        [self drawPhotoFromOrderedList:participantsToDisplay];
        
    }
    return  nil;
}

+(UIImage *) drawPhotoFromOrderedList:(NSOrderedSet*) orderedList {
    
    CGSize newSize = CGSizeMake(128, 128);
    
    if ([orderedList count] == 1) {
        
        UIImage *img1, *img2 = nil;
        id obj = orderedList[0];
        if([obj isKindOfClass:[Participant class]]) {
            img1 = ((Participant*)obj).contact.getContactImage;
            img2 = [UIColor.lightGrayColor imageFromColor];
            
            UIGraphicsBeginImageContextWithOptions(newSize, NO, 0);
            
            // participant 1 : left half of the avatar
            CGRect rect1 = CGRectMake(img1.size.width/4, 0, img1.size.width/2, img1.size.height);
            UIImage *croppedImg1 = [self cropImage:img1 withRect:rect1];
            [croppedImg1 drawInRect:CGRectMake(0, 0, newSize.width/2, newSize.height)];
            
            // participant 2 : right half of the avatar
            CGRect rect2 = CGRectMake(img2.size.width/4, 0, img2.size.width/2, img2.size.height);
            UIImage *croppedImg2 = [self cropImage:img2 withRect:rect2];
            [croppedImg2 drawInRect:CGRectMake(newSize.width/2, 0, newSize.width/2, newSize.height)];
            
            UIImage *generatedImageFromParticipants = UIGraphicsGetImageFromCurrentImageContext();
            
            UIGraphicsEndImageContext();
            return generatedImageFromParticipants;
            
        }
        else {
            [self setPhotoForPeer:obj];
        }
        
        
    }
    
    if ([orderedList count] == 2) {
        
        UIImage *img1, *img2 = nil;
        id obj0 = orderedList[0];
        id obj1 = orderedList[1];
        if([obj0 isKindOfClass:[Participant class]] && [obj1 isKindOfClass:[Participant class]]){
            // This will open its own CG context.
            img1 = ((Participant*)obj0).contact.getContactImage;
            img2 = ((Participant*)obj1).contact.getContactImage;
        } else {
            // This will open its own CG context.
            //TODO: find when its come to this case!!
            Contact *contact0 = (Contact *)obj0;
            Contact *contact1 = (Contact *)obj1;
            img1 = contact0.getContactImage;
            img2 = contact1.getContactImage;
        }
        UIGraphicsBeginImageContextWithOptions(newSize, NO, 0);
        
        // participant 1 : left half of the avatar
        CGRect rect1 = CGRectMake(img1.size.width/4, 0, img1.size.width/2, img1.size.height);
        UIImage *croppedImg1 = [self cropImage:img1 withRect:rect1];
        [croppedImg1 drawInRect:CGRectMake(0, 0, newSize.width/2, newSize.height)];
        
        // participant 2 : right half of the avatar
        CGRect rect2 = CGRectMake(img2.size.width/4, 0, img2.size.width/2, img2.size.height);
        UIImage *croppedImg2 = [self cropImage:img2 withRect:rect2];
        [croppedImg2 drawInRect:CGRectMake(newSize.width/2, 0, newSize.width/2, newSize.height)];
        
        UIImage *generatedImageFromParticipants = UIGraphicsGetImageFromCurrentImageContext();
        
        UIGraphicsEndImageContext();
        return generatedImageFromParticipants;
    }
    
    if ([orderedList count] >= 3) {
        
        UIImage *img1, *img2 , *img3 = nil;
        id obj0 = orderedList[0];
        id obj1 = orderedList[1];
        id obj2 = orderedList[2];
        if([obj0 isKindOfClass:[Participant class]] && [obj1 isKindOfClass:[Participant class]] && [obj2 isKindOfClass:[Participant class]]){
            // This will open its own CG context.
            img1 = ((Participant*)obj0).contact.getContactImage;
            img2 = ((Participant*)obj1).contact.getContactImage;
            img3 = ((Participant*)obj2).contact.getContactImage;
        } else {
            Contact *contact1 = (Contact *)obj0;
            Contact *contact2 = (Contact *)obj1;
            Contact *contact3 = (Contact *)obj2;
            img1 = contact1.getContactImage;
            img2 = contact2.getContactImage;
            img3 = contact3.getContactImage;
        }
        UIGraphicsBeginImageContextWithOptions(newSize, NO, 0);
        
        // participant 1 : left half of the avatar
        CGRect rect1 = CGRectMake(img1.size.width/4, 0, img1.size.width/2, img1.size.height);
        UIImage *croppedImg1 = [self cropImage:img1 withRect:rect1];
        [croppedImg1 drawInRect:CGRectMake(0, 0, newSize.width/2, newSize.height)];
        
        // participant 2 : right top quarter of the avatar
        [img2 drawInRect:CGRectMake(newSize.width/2, 0, newSize.width/2, newSize.height/2)];
        
        // participant 3 : right bottom quarter of the avatar
        [img3 drawInRect:CGRectMake(newSize.width/2, newSize.height/2, newSize.width/2, newSize.height/2)];
        
        UIImage *generatedImageFromParticipants = UIGraphicsGetImageFromCurrentImageContext();
        
        UIGraphicsEndImageContext();
        return generatedImageFromParticipants;
    }
    return nil;
}


@end
