//
//  RNMonthYearPicker.m
//  react-native-month-year-picker
//
//  Created by Kien Tran on 08/04/2023.
//

#import "RNMonthYearPicker.h"
#import <React/RCTConvert.h>
#import <React/RCTUtils.h>

#define DEFAULT_YEAR_SIZE 408
#define DEFAULT_MONTH_SIZE 3000


@implementation RNMonthYearPicker

NSCalendar *gregorian;
NSDateFormatter *df;
NSDateComponents *maxComponents;
NSDateComponents *minComponents;

NSMutableArray *years;
NSInteger selectedMonthRow;
NSInteger selectedYearRow;

- (instancetype)initWithFrame:(CGRect)frame
{
    if ((self = [super initWithFrame:frame])) {
        self.delegate = self;
        gregorian = [NSCalendar currentCalendar];
        df = [[NSDateFormatter alloc] init];
        [df setDateFormat:@"MMMM"];
        _value = nil;
        _minimumDate = nil;
        _maximumDate = nil;
    }
    return self;
}

RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:(NSCoder *)aDecoder)

- (void)setLocale:(NSLocale *)useLocale {
    [df setLocale:useLocale];
}

- (void)initYears:(NSInteger)selectedYear {
    years = [NSMutableArray array];
    for(NSInteger i = selectedYear - DEFAULT_YEAR_SIZE; i <= selectedYear + DEFAULT_YEAR_SIZE; i ++) {
        [years addObject: [NSNumber numberWithLong:i]];
    }
}

- (void)setValue:(nonnull NSDate *)value {
    if (value != _value) {
        NSDateComponents *selectedDateComponents = [gregorian components:(NSCalendarUnitMonth|NSCalendarUnitYear) fromDate:value];
        if (!_value) {
            [self initYears: [selectedDateComponents year]];
            selectedMonthRow = (DEFAULT_MONTH_SIZE / 2) + [selectedDateComponents month];
            selectedYearRow = DEFAULT_YEAR_SIZE;
            [self setSelectedRows: NO];
        }
        _value = value;
    }
}

- (void)setMaximumDate:(NSDate *)maximumDate {
    _maximumDate = maximumDate;
    maxComponents = _maximumDate ? [gregorian components:NSCalendarUnitMonth | NSCalendarUnitYear fromDate:_maximumDate] : nil;
}

- (void)setMinimumDate:(NSDate *)minimumDate {
    _minimumDate = minimumDate;
    minComponents = _minimumDate ? [gregorian components:NSCalendarUnitMonth | NSCalendarUnitYear fromDate:_minimumDate] : nil;
}

- (void)setSelectedRows:(BOOL)animated {
    dispatch_async(dispatch_get_main_queue(), ^{
        [self selectRow:selectedMonthRow inComponent:0 animated:animated];
        [self selectRow:selectedYearRow inComponent:1 animated:animated];
    });
}

#pragma mark - UIPickerViewDataSource protocol
// number of columns
- (NSInteger)numberOfComponentsInPickerView:(nonnull UIPickerView *)pickerView {
    return 2;
}

// number of rows
- (NSInteger)pickerView:(nonnull UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
    switch (component) {
        case 0:
            return DEFAULT_MONTH_SIZE;
        case 1:
            return (DEFAULT_YEAR_SIZE * 2) + 1;
            break;
        default:
            return 0;
    }
}

#pragma mark - UIPickerViewDelegate methods
// row titles
- (NSAttributedString *)pickerView:(nonnull UIPickerView *)pickerView attributedTitleForRow:(NSInteger)row forComponent:(NSInteger)component {
    NSString *title;
    switch (component) {
        case 0: {
            NSDateComponents *comps = [[NSDateComponents alloc] init];
            [comps setMonth: row % 12 != 0 ? row % 12 : 12];
            title = [NSString stringWithFormat:@"%@", [df stringFromDate:[gregorian dateFromComponents:comps]]];
            break;
        }
        case 1:
            title = [NSString stringWithFormat:@"%@", years[row]];
            break;
        default:
            return nil;
    }
    UIColor *color = _textColor ?: [self defaultTextColor];
return [[NSAttributedString alloc] initWithString:title attributes:@{NSForegroundColorAttributeName: color}];
}

- (UIColor *)defaultTextColor {
    if (@available(iOS 13.0, *)) {
        return [UIColor labelColor];
    }
    return [UIColor blackColor];
}

+ (UIColor *)colorFromString:(NSString *)colorString {
    if (!colorString) return nil;
    NSString *trimmed = [[colorString stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] lowercaseString];
    if (trimmed.length == 0) return nil;

    if (![trimmed hasPrefix:@"#"]) {
        NSDictionary<NSString *, UIColor *> *namedColors = @{
            @"black":       [UIColor blackColor],
            @"white":       [UIColor whiteColor],
            @"red":         [UIColor redColor],
            @"green":       [UIColor greenColor],
            @"blue":        [UIColor blueColor],
            @"yellow":      [UIColor yellowColor],
            @"orange":      [UIColor orangeColor],
            @"purple":      [UIColor purpleColor],
            @"gray":        [UIColor grayColor],
            @"grey":        [UIColor grayColor],
            @"cyan":        [UIColor cyanColor],
            @"magenta":     [UIColor magentaColor],
            @"transparent": [UIColor clearColor],
            @"clear":       [UIColor clearColor],
        };
        return namedColors[trimmed];
    }

    NSString *hex = [trimmed substringFromIndex:1];
    if (hex.length == 3) {
        NSString *r = [hex substringWithRange:NSMakeRange(0, 1)];
        NSString *g = [hex substringWithRange:NSMakeRange(1, 1)];
        NSString *b = [hex substringWithRange:NSMakeRange(2, 1)];
        hex = [NSString stringWithFormat:@"%@%@%@%@%@%@", r, r, g, g, b, b];
    }
    if (hex.length != 6 && hex.length != 8) return nil;
    unsigned int rgba = 0;
    NSScanner *scanner = [NSScanner scannerWithString:hex];
    if (![scanner scanHexInt:&rgba] || !scanner.isAtEnd) return nil;
    if (hex.length == 6) {
        return [UIColor colorWithRed:((rgba >> 16) & 0xFF) / 255.0
                               green:((rgba >> 8) & 0xFF) / 255.0
                                blue:(rgba & 0xFF) / 255.0
                               alpha:1.0];
    }
    return [UIColor colorWithRed:((rgba >> 24) & 0xFF) / 255.0
                           green:((rgba >> 16) & 0xFF) / 255.0
                            blue:((rgba >> 8) & 0xFF) / 255.0
                           alpha:(rgba & 0xFF) / 255.0];
}

- (void)getSelectedMonthRow:(NSInteger)row {
    NSInteger month = row % 12 != 0 ? row % 12 : 12;
    NSInteger year = [years[selectedYearRow] longValue];
    if (minComponents && year == [minComponents year] && month < [minComponents month]) {
        selectedMonthRow = row + [minComponents month] - month;
    } else if (maxComponents && year == [maxComponents year] && month > [maxComponents month]) {
        selectedMonthRow = row + [maxComponents month] - month;
    } else {
        selectedMonthRow = row;
    }
}

- (void)getSelectedYearRow:(NSInteger)row {
    NSInteger year = [years[row] longValue];
    if (minComponents && (year < [minComponents year])) {
        selectedYearRow = [years indexOfObject:[NSNumber numberWithInteger:[minComponents year]]];
    } else if (maxComponents && year > [maxComponents year]) {
        selectedYearRow = [years indexOfObject:[NSNumber numberWithInteger:[maxComponents year]]];
    } else {
        selectedYearRow = row;
    }
}

- (void)pickerView:(__unused UIPickerView *)pickerView
      didSelectRow:(NSInteger)row inComponent:(__unused NSInteger)component {
    switch (component) {
        case 0:
            [self getSelectedMonthRow:row];
            break;
        case 1:
            [self getSelectedYearRow:row];
            [self getSelectedMonthRow:selectedMonthRow];
            break;
        default:
            return;
    }
    [self setSelectedRows: YES];
    if (_onChange) {
        _onChange(@{
                @"newDate": [NSString stringWithFormat: @"%@-%@", [NSString stringWithFormat: @"%ld", selectedMonthRow % 12 != 0 ? selectedMonthRow % 12 : 12], [NSString stringWithFormat: @"%@", years[selectedYearRow]]]
        });
    }
}
@end
