/*
 * 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 "WXRuleManager.h"
#import "WXThreadSafeMutableDictionary.h"
#import "WXUtility.h"
#import "WXConvert.h"
#import "WXHandlerFactory.h"
#import "WXURLRewriteProtocol.h"
#import "WXComponentManager.h"
#import "WXDefine.h"
#import "WXSDKEngine.h"

@interface WXRuleManager()
@property (nonatomic, strong) WXThreadSafeMutableDictionary *fontStorage;
@end

@implementation WXRuleManager

static WXRuleManager *_sharedInstance = nil;

+ (WXRuleManager *)sharedInstance
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        if (!_sharedInstance) {
            _sharedInstance = [[self alloc] init];
            _sharedInstance.fontStorage = [[WXThreadSafeMutableDictionary alloc] init];
        }
    });
    return _sharedInstance;
}

- (void)removeRule:(NSString *)type rule:(NSDictionary *)rule
{
    if ([type isEqualToString:@"fontFace"]) {
        if (rule[@"fontFamily"]) {
            [_fontStorage removeObjectForKey:rule[@"fontFamily"]];
        } else {
            [_fontStorage removeAllObjects];
        }
    }
}

- (void)addRule:(NSString*)type rule:(NSDictionary *)rule
{
    if ([type isEqualToString:@"fontFace"] && [rule[@"src"] isKindOfClass:[NSString class]]) {
        if (rule[@"src"] && rule[@"fontFamily"] && ![WXUtility isBlankString:rule[@"src"]]) {
            NSString *ruleSrc = [WXConvert NSString:rule[@"src"]];
            if (!ruleSrc) {
                WXLogError(@"%@ is illegal for font src",rule[@"src"]);
                return;
            }
            NSUInteger start = [rule[@"src"] rangeOfString:@"url('"].location + @"url('".length;
            NSUInteger end  = [rule[@"src"] rangeOfString:@"')" options:NSBackwardsSearch].location;
            if (end <= start || start == NSNotFound || end == NSNotFound) {
                WXLogWarning(@"font url is not specified");
                return;
            }
            
            NSString *fontSrc = [rule[@"src"] substringWithRange:NSMakeRange(start, end-start)];
            NSString *newURL = [fontSrc copy];
            WX_REWRITE_URL(fontSrc, WXResourceTypeFont, self.instance)
            
            if (!newURL) {
                return;
            }
            
            fontSrc = newURL;
            WXThreadSafeMutableDictionary * fontFamily = [self.fontStorage objectForKey:rule[@"fontFamily"]];
            if (fontFamily && [fontFamily[@"tempSrc"] isEqualToString:fontSrc]) {
                // if the new src is same as src in dictionary , ignore it, or update it
                return;
            }
            if (!fontFamily) {
                fontFamily = [[WXThreadSafeMutableDictionary alloc] init];
            }
            NSURL *fontURL = [NSURL URLWithString:fontSrc];
            if (!fontURL) {
                // if the fontSrc string is illegal, the fontURL will be nil
                return;
            }
            if([fontURL isFileURL]){
                [fontFamily setObject:fontSrc forKey:@"src"];
            }else {
                [fontFamily setObject:fontSrc forKey:@"tempSrc"];
            }
            
            [_fontStorage setObject:fontFamily forKey:rule[@"fontFamily"]];
            // remote font file
            NSString* instanceId = self.instance ? (self.instance.instanceId ?: @"") : @"";
            NSString *fontfile = [NSString stringWithFormat:@"%@/%@",WX_FONT_DOWNLOAD_DIR,[WXUtility md5:[fontURL absoluteString]]];
            if ([WXUtility isFileExist:fontfile]) {
                // if has been cached, load directly
                [fontFamily setObject:[NSURL fileURLWithPath:fontfile] forKey:@"localSrc"];
                [[NSNotificationCenter defaultCenter] postNotificationName:WX_ICONFONT_READY_NOTIFICATION object:nil userInfo:@{@"instanceId": instanceId, @"fontFamily": rule[@"fontFamily"], @"filePath": fontfile}];
                return;
            }
            __weak typeof(self) weakSelf = self;
            [WXUtility getIconfont:fontURL completion:^(NSURL * _Nonnull url, NSError * _Nullable error) {
                if (!error && url) {
                    // load success
                    WXThreadSafeMutableDictionary * dictForFontFamily = [weakSelf.fontStorage objectForKey:rule[@"fontFamily"]];
                    NSString *fontSrc = [dictForFontFamily objectForKey:@"tempSrc"];
                    if (fontSrc) {
                        // only remote font will be mark as tempSrc
                        [dictForFontFamily setObject:fontSrc forKey:@"src"];
                    }
                    [dictForFontFamily setObject:url forKey:@"localSrc"];
                    
                    [[NSNotificationCenter defaultCenter] postNotificationName:WX_ICONFONT_DOWNLOAD_NOTIFICATION object:nil userInfo:@{@"fontFamily":rule[@"fontFamily"]}];
                    [[NSNotificationCenter defaultCenter] postNotificationName:WX_ICONFONT_READY_NOTIFICATION object:nil userInfo:@{@"instanceId": instanceId, @"fontFamily": rule[@"fontFamily"], @"filePath": [url path]}];
                } else {
                    //there was some errors during loading
                    WXLogError(@"load font failed %@",error.description);
                }
            }];
        }
    }
}

- (WXThreadSafeMutableDictionary *)getRule:(NSString *)type
{
    if ([type isEqualToString:@"fontFace"]) {
        return _fontStorage;
    }
    
    return nil;
}

@end
