package com.pdftron.reactnative.utils;

import android.content.ContentResolver;
import android.content.Context;
import android.net.Uri;
import android.util.Base64;
import android.util.Log;
import android.webkit.URLUtil;

import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.ReadableMapKeySetIterator;
import com.pdftron.pdf.PDFDraw;
import com.pdftron.pdf.Page;
import com.pdftron.pdf.utils.Utils;
import com.pdftron.pdf.PDFDoc;

import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.File;
import java.io.FileOutputStream;
import java.net.URLEncoder;

import static com.pdftron.reactnative.utils.Constants.*;

public class ReactUtils {

    private static final String TAG = ReactUtils.class.getName();

    public static Uri getUri(Context context, String path, boolean isBase64, String base64Extension) {
        if (context == null || path == null) {
            return null;
        }
        try {
            if (isBase64) {
                byte[] data = Base64.decode(path, Base64.DEFAULT);
                File tempFile = File.createTempFile("tmp", base64Extension);
                FileOutputStream fos = null;
                try {
                    fos = new FileOutputStream(tempFile);
                    IOUtils.write(data, fos);
                    return Uri.fromFile(tempFile);
                } finally {
                    IOUtils.closeQuietly(fos);
                }
            }
            Uri fileUri = Uri.parse(path);
            if (ContentResolver.SCHEME_ANDROID_RESOURCE.equals(fileUri.getScheme())) {
                String resNameWithExtension = fileUri.getLastPathSegment();
                String extension = FilenameUtils.getExtension(resNameWithExtension);
                String resName = FilenameUtils.removeExtension(resNameWithExtension);
                int resId = Utils.getResourceRaw(context, resName);
                if (resId != 0) {
                    File file = Utils.copyResourceToLocal(context, resId,
                            resName, "." + extension);
                    if (null != file && file.exists()) {
                        fileUri = Uri.fromFile(file);
                    }
                }
            } else if (ContentResolver.SCHEME_FILE.equals(fileUri.getScheme())) {
                File file = new File(fileUri.getPath());
                fileUri = Uri.fromFile(file);
            } else if (URLUtil.isHttpUrl(path) || URLUtil.isHttpsUrl(path)) {
                // this is a link uri, let's encode the file name
                if (path.contains(" ")) {
                    String filename = FilenameUtils.getName(path);
                    if (filename.contains("?")) {
                        filename = filename.substring(0, filename.indexOf("?")); // remove query params
                    }
                    String encodedName = URLEncoder.encode(filename, "UTF-8").replace("+", "%20");
                    String newUrl = path.replace(filename, encodedName);
                    return Uri.parse(newUrl);
                }
            }
            return fileUri;
        } catch (Exception ex) {
            Log.e(TAG, ex.getMessage() != null ? ex.getMessage() : "unknown error");
            ex.printStackTrace();
        }
        return null;
    }

    public static JSONObject convertMapToJson(ReadableMap readableMap) throws JSONException {
        JSONObject object = new JSONObject();
        ReadableMapKeySetIterator iterator = readableMap.keySetIterator();
        while (iterator.hasNextKey()) {
            String key = iterator.nextKey();
            switch (readableMap.getType(key)) {
                case Null:
                    object.put(key, JSONObject.NULL);
                    break;
                case Boolean:
                    object.put(key, readableMap.getBoolean(key));
                    break;
                case Number:
                    object.put(key, readableMap.getDouble(key));
                    break;
                case String:
                    object.put(key, readableMap.getString(key));
                    break;
                case Map:
                    object.put(key, convertMapToJson(readableMap.getMap(key)));
                    break;
                case Array:
                    object.put(key, convertArrayToJson(readableMap.getArray(key)));
                    break;
            }
        }
        return object;
    }

    public static JSONArray convertArrayToJson(ReadableArray readableArray) throws JSONException {
        JSONArray array = new JSONArray();
        for (int i = 0; i < readableArray.size(); i++) {
            switch (readableArray.getType(i)) {
                case Null:
                    break;
                case Boolean:
                    array.put(readableArray.getBoolean(i));
                    break;
                case Number:
                    array.put(readableArray.getDouble(i));
                    break;
                case String:
                    array.put(readableArray.getString(i));
                    break;
                case Map:
                    array.put(convertMapToJson(readableArray.getMap(i)));
                    break;
                case Array:
                    array.put(convertArrayToJson(readableArray.getArray(i)));
                    break;
            }
        }
        return array;
    }

    public static String exportAsImageHelper(PDFDoc doc, int pageNumber, double dpi, String exportFormat, boolean transparent) {
        PDFDraw draw = null;
        try {
            draw = new PDFDraw();
            draw.setDPI(dpi);
            draw.setPageTransparent(transparent);
            if (pageNumber <= doc.getPageCount() && pageNumber >= 1) {
                Page pg = doc.getPage(pageNumber);
                String ext = "png";
                if (KEY_EXPORT_FORMAT_BMP.equals(exportFormat)) {
                    ext = "bmp";
                } else if (KEY_EXPORT_FORMAT_JPEG.equals(exportFormat)) {
                    ext = "jpeg";
                }
                File tempFile = File.createTempFile("tmp", "." + ext);
                draw.export(pg, tempFile.getAbsolutePath(), exportFormat);
                return tempFile.getAbsolutePath();
            }
            return null;
        } catch (Exception ex) {
            throw new RuntimeException(ex);
        } finally {
            if (draw != null) {
                try {
                    draw.destroy();
                } catch (Exception ignored) {
                }
            }
        }
    }
}
