/*
 * Copyright (C) 2015 Emanuel Moecklin
 *
 * 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.onegravity.rteditor.utils;

import android.content.Context;
import android.content.res.Configuration;
import android.net.Uri;
import android.util.DisplayMetrics;
import android.view.Display;
import android.view.WindowManager;

import com.onegravity.rteditor.api.RTApi;
import com.onegravity.rteditor.utils.io.IOUtils;

import java.io.Closeable;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.text.Bidi;
import java.util.Locale;

/**
 * Miscellaneous helper methods
 */
public abstract class Helper {

    private static float sDensity = Float.MAX_VALUE;
    private static float sDensity4Fonts = Float.MAX_VALUE;

    public static void closeQuietly(Closeable closeable) {
        IOUtils.closeQuietly(closeable);
    }

    public static float getDisplayDensity() {
        synchronized (Helper.class) {
            if (sDensity == Float.MAX_VALUE) {
                sDensity = getDisplayMetrics().density;
            }
            return sDensity;
        }
    }

    /**
     * Convert absolute pixels to scale dependent pixels.
     * This scales the size by scale dependent screen density (accessibility setting) and
     * the global display setting for message composition fields
     */
    public static int convertPxToSp(int pxSize) {
        return Math.round((float) pxSize * getDisplayDensity4Fonts());
    }

    /**
     * Convert scale dependent pixels to absolute pixels.
     * This scales the size by scale dependent screen density (accessibility setting) and
     * the global display setting for message composition fields
     */
    public static int convertSpToPx(int spSize) {
        return Math.round((float) spSize / getDisplayDensity4Fonts());
    }

    private static DisplayMetrics getDisplayMetrics() {
        Display display = ((WindowManager) RTApi.getApplicationContext().getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
        DisplayMetrics metrics = new DisplayMetrics();
        display.getMetrics(metrics);
        return metrics;
    }

    private static float getDisplayDensity4Fonts() {
        synchronized (Helper.class) {
            if (sDensity4Fonts == Float.MAX_VALUE) {
                sDensity4Fonts = getDisplayMetrics().density * getFontScale();
            }
            return sDensity4Fonts;
        }
    }

    private static float getFontScale() {
        Configuration config = RTApi.getApplicationContext().getResources().getConfiguration();
        return config.fontScale;
    }

    /**
     * This method encodes the query part of an url
     * @param url an url (e.g. http://www.1gravity.com?query=üö)
     * @return The url with an encoded query, e.g. http://www.1gravity.com?query%3D%C3%BC%C3%B6
     */
    public static String encodeQuery(String url) {
        Uri uri = Uri.parse(url);

        try {
            String query = uri.getQuery();
            String encodedQuery = query != null ? URLEncoder.encode(query, "UTF-8") : null;
            URI tmp = new URI(uri.getScheme(), uri.getAuthority(), uri.getPath(), null, uri.getFragment());
            return tmp + (encodedQuery != null && encodedQuery.length() > 0 ? "?" + encodedQuery : "");
        }
        catch (UnsupportedEncodingException ignore) {}
        catch (URISyntaxException ignore) {}

        return uri.toString();
    }

    /**
     * This method decodes an url with encoded query string
     * @param url an url with encoded query string (e.g. http://www.1gravity.com?query%3D%C3%BC%C3%B6)
     * @return The decoded url, e.g. http://www.1gravity.com?query=üö
     */
    public static String decodeQuery(String url) {
        try {
            return URLDecoder.decode(url, "UTF-8");
        }
        catch (UnsupportedEncodingException ignore) {}

        return url;
    }

    /**
     * This method determines if the direction of a substring is right-to-left.
     * If the string is empty that determination is based on the default system language
     * Locale.getDefault().
     * The method can handle invalid substring definitions (start > end etc.), in which case the
     * method returns False.
     *
     * @return True if the text direction is right-to-left, false otherwise.
     */
    public static boolean isRTL(CharSequence s, int start, int end) {
        if (s == null || s.length() == 0) {
            // empty string --> determine the direction from the default language
            return isRTL(Locale.getDefault());
        }

        if (start == end) {
            // if no character is selected we need to expand the selection
            start = Math.max(0, --start);
            if (start == end) {
                end = Math.min(s.length(), ++end);
            }
        }

        try {
            Bidi bidi = new Bidi(s.subSequence(start, end).toString(), Bidi.DIRECTION_DEFAULT_LEFT_TO_RIGHT);
            return ! bidi.baseIsLeftToRight();
        }
        catch (IndexOutOfBoundsException e) {
            return false;
        }
    }

    private static boolean isRTL(Locale locale) {
        int directionality = Character.getDirectionality(locale.getDisplayName().charAt(0));
        return directionality == Character.DIRECTIONALITY_RIGHT_TO_LEFT ||
                directionality == Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC;
    }

}

@@ -1347,16 +1347,112 @@
 VALUE;%0A%0A
+    private static final int LEADING_MARGIN = 28;%0A    private static int sLeadingMarging = -1;%0A%0A
     publ
@@ -3285,32 +3285,286 @@
 ntScale;%0A    %7D%0A%0A
+    public static int getLeadingMarging() %7B%0A        if (sLeadingMarging == -1) %7B%0A            float density = Helper.getDisplayDensity();%0A            sLeadingMarging = Math.round(LEADING_MARGIN * density);%0A        %7D%0A        return sLeadingMarging;%0A    %7D%0A%0A
     /**%0A     * T

Add the missing getLeadingMargin method to the Helper class