/*
 * Copyright 2015 Priyesh Patel
 *
 * Licensed 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.
 */

package com.chromium.fontinstaller.core;

import android.content.Context;
import android.util.Pair;

import com.chromium.fontinstaller.models.Font;
import com.chromium.fontinstaller.models.FontPackage;
import com.chromium.fontinstaller.models.Style;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.Response;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

import okio.BufferedSink;
import okio.Okio;
import rx.Observable;

public class FontDownloader {

    private static final OkHttpClient CLIENT = new OkHttpClient();

    public static Observable<File> downloadAllFonts(FontPackage fontPackage, Context context) {
        createCacheDirectory(fontPackage, context);
        return downloadFonts(fontPackage, context, allFontFinder);
    }

    public static Observable<File> downloadStyledFonts(FontPackage fontPackage, Context context, Style... styles) {
        createCacheDirectory(fontPackage, context);
        return downloadFonts(fontPackage, context, styledFontFinder(Arrays.asList(styles)));
    }

    private static Observable<File> downloadFile(final String url, final String path) {
        return Observable.create(subscriber -> {
            final Request request = new Request.Builder().url(url).build();
            try {
                if (!subscriber.isUnsubscribed()) {
                    final Response response = CLIENT.newCall(request).execute();
                    final File file = new File(path);
                    final BufferedSink sink = Okio.buffer(Okio.sink(file));
                    sink.writeAll(response.body().source());
                    sink.close();
                    if (file.exists()) {
                        subscriber.onNext(file);
                        subscriber.onCompleted();
                    } else subscriber.onError(new IOException("File was not downloaded"));
                }
            } catch (IOException e) {
                subscriber.onError(e);
            }
        });
    }

    private static Observable<File> downloadFiles(ArrayList<Pair<String, String>> files) {
        return Observable.from(files).flatMap(p -> downloadFile(p.first, p.second));
    }

    private static Observable<File> downloadFonts(FontPackage fontPackage, Context context, FontFinder finder) {
        ArrayList<Pair<String, String>> urlsAndPaths = new ArrayList<>();
        for (Font font : finder.findFonts(fontPackage)) {
            String path = context.getExternalCacheDir() + File.separator +
                    fontPackage.getNameFormatted() + File.separator + font.getName();
            urlsAndPaths.add(new Pair<>(font.getUrl(), path));
        }
        return downloadFiles(urlsAndPaths);
    }

    private interface FontFinder {
        List<Font> findFonts(FontPackage fontPackage);
    }

    private static FontFinder allFontFinder = FontPackage::getFontList;

    private static FontFinder styledFontFinder(List<Style> acceptedStyles) {
        return fontPackage -> {
            Map<Font, Style> fontStyleMap = fontPackage.getFontStyleMap();
            ArrayList<Font> rightFonts = new ArrayList<>();
            for (Map.Entry<Font, Style> f : fontStyleMap.entrySet()) {
                if (acceptedStyles.contains(f.getValue())) {
                    rightFonts.add(f.getKey());
                }
            }
            return rightFonts;
        };
    }

    private static void createCacheDirectory(FontPackage fontPackage, Context context) {
        File dir = new File(context.getExternalCacheDir() +
                File.separator + fontPackage.getNameFormatted());
        dir.mkdirs();
    }

}

@@ -2073,63 +2073,79 @@
 nal 
-Response response = CLIENT.newCall(request).execute();%0A
+File file = new File(path);%0A                    if (!file.exists()) %7B%0A 
     
@@ -2164,42 +2164,76 @@
     
+   
 final 
-File file = new File(path);%0A
+Response response = CLIENT.newCall(request).execute();%0A    
     
@@ -2320,24 +2320,28 @@
             
+    
 sink.writeAl
@@ -2385,24 +2385,28 @@
             
+    
 sink.close()
@@ -2431,33 +2431,10 @@
     
-if (file.exists()) %7B%0A    
+%7D%0A
     
@@ -2486,36 +2486,32 @@
                 
-    
 subscriber.onCom
@@ -2524,99 +2524,8 @@
 ();%0A
-                    %7D else subscriber.onError(new IOException(%22File was not downloaded%22));%0A
     
@@ -4184,32 +4184,16 @@
 eDir() +
-%0A               
  File.se

Make use of cached fonts