package com.zxhl.cms.utils;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.AppOpsManager;
import android.app.usage.UsageStats;
import android.app.usage.UsageStatsManager;
import android.content.ComponentName;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.net.Uri;
import android.os.Build;
import android.text.TextUtils;
import android.util.Base64;
import android.util.Log;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.View;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;

import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.RecyclerView;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.zxhl.cms.AppContext;
import com.zxhl.cms.ad.upload.model.NewsEntity;
import com.zxhl.cms.common.Constant;
import com.zxhl.cms.common.NetConfig;
import com.zxhl.cms.net.model.news.NewsHistoryEntity;
import com.zxhl.cms.net.model.news.TabEntity;
import com.zxhl.cms.net.model.other.NavEntity;
import com.zxhl.cms.net.model.uc.StepData;
import com.zxhl.cms.net.SettingPreference;
import com.zxhl.cms.db.DBCallback;
import com.zxhl.cms.db.DBConfig;
import com.zxhl.cms.db.DataSupport;
import com.zxhl.cms.net.model.uc.UserInfo;
import com.zxhl.cms.router.RounterApi;
import com.zxhl.cms.router.RounterBus;
import com.zxhl.cms.widget.TabLayout;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URLDecoder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;

/**
 * Created by gaoleichao on 2018/4/25.
 */

public class Utils {

    private static String oldMsg;
    protected static Toast toast = null;
    private static long oneTime = 0;
    private static long twoTime = 0;

    public static void showToast(Context context, final String str) {
        MainLooper.Companion.get().post(new Runnable() {
            @Override
            public void run() {
                String msg = str;
                if (msg == null || TextUtils.isEmpty(msg))
                    return;

                if (msg.contains("failed to connect to") || msg.contains("502") || msg.contains("404") || msg.contains("failed to connect to"))
                    msg = "网络不给力，请重新尝试";

                if (toast == null) {
                    toast = Toast.makeText(AppContext.get(), msg, Toast.LENGTH_SHORT);
                    toast.show();
                    oneTime = System.currentTimeMillis();
                } else {
                    twoTime = System.currentTimeMillis();
                    if (msg.equals(oldMsg)) {
                        if (twoTime - oneTime > Toast.LENGTH_SHORT) {
                            toast.show();
                        }
                    } else {
                        oldMsg = msg;
                        toast.setText(msg);
                        toast.show();
                    }
                }
                oneTime = twoTime;
            }
        });
    }

    public static void destory(View view) {
        toDestory(view);
    }

    private static void toDestory(Object obj) {
        if (obj == null)
            return;
        Class clazz = obj.getClass();
        Field[] fields = clazz.getDeclaredFields();
        for (int i = 0; i < fields.length; i++) {
            Field field = fields[i];
            field.setAccessible(true);
            try {
                field.set(obj, null);
            } catch (Exception e) {
            }
        }
    }


    public static int dip2px(int dipValue) {
        final float scale = AppContext.get().getResources().getDisplayMetrics().density;
        return (int) (dipValue * scale + 0.5f);
    }

    public static int px2dip(Context context, float pxValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (pxValue / scale + 0.5f);
    }

    public static String getLocalVersionName(Context ctx) {
        String localVersion = "";
        try {
            PackageInfo packageInfo = ctx.getApplicationContext()
                    .getPackageManager()
                    .getPackageInfo(ctx.getPackageName(), 0);
            localVersion = packageInfo.versionName;
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }
        return localVersion;
    }

    /**
     * 转换dip为px
     *
     * @param context
     * @param dip
     * @return
     */
    public static int convertDipOrPx(Context context, float dip) {
        float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dip * scale + 0.5f * (dip >= 0 ? 1 : -1));
    }

    /**
     * 判断当前程序是否前台进程
     *
     * @param context
     * @return
     */
    public static boolean isCurAppTop(Context context) {
        if (context == null) {
            return false;
        }
        String curPackageName = context.getPackageName();
        android.app.ActivityManager am = (android.app.ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
        List<android.app.ActivityManager.RunningTaskInfo> list = am.getRunningTasks(1);
        if (list != null && list.size() > 0) {
            android.app.ActivityManager.RunningTaskInfo info = list.get(0);
            String topPackageName = info.topActivity.getPackageName();
            String basePackageName = info.baseActivity.getPackageName();
            if (topPackageName.equals(curPackageName) && basePackageName.equals(curPackageName)) {
                return true;
            }
        }
        return false;
    }

    public static String key(String key) {
        StringBuffer sb = new StringBuffer();
        char[] ch = key.toCharArray();
        for (int i = ch.length - 1; i >= 0; i--) {
            sb.append(ch[i]);
        }

        return sb.toString();
    }


    public static <E> String list2String(List<E> list) {

        return new Gson().toJson(list);
    }

    public static String obj2Str(Object obj) {
        if (obj == null) {
            return "";
        }
        return new Gson().toJson(obj);
    }

    public static Object str2Obj(String json, Class beanClass) {
        Gson gson = new Gson();
        Object res = gson.fromJson(json, beanClass);
        return res;
    }

    public static List<NewsEntity> str2list(String json) {
        return new Gson().fromJson(json,
                new TypeToken<List<NewsEntity>>() {
                }.getType());
    }

    public static List<NewsHistoryEntity> str2listHistory(String json) {
        return new Gson().fromJson(json,
                new TypeToken<List<NewsHistoryEntity>>() {
                }.getType());
    }

    public static List<TabEntity> str2listTab(String json) {
        return new Gson().fromJson(json,
                new TypeToken<List<TabEntity>>() {
                }.getType());
    }

    public static List<StepData> str2listStep(String json) {
        return new Gson().fromJson(json,
                new TypeToken<List<StepData>>() {
                }.getType());
    }

    public static List<NavEntity> str2listNav(String json) {
        return new Gson().fromJson(json,
                new TypeToken<List<NavEntity>>() {
                }.getType());
    }

    public static <T> List<T> str2listObj(String json, Class clazz) {
        Type type = new ParameterizedTypeImpl(clazz);
        List<T> list = new Gson().fromJson(json, type);
        return list;
    }

    private static class ParameterizedTypeImpl implements ParameterizedType {
        Class clazz;

        public ParameterizedTypeImpl(Class clz) {
            clazz = clz;
        }

        @Override
        public Type[] getActualTypeArguments() {
            return new Type[]{clazz};
        }

        @Override
        public Type getRawType() {
            return List.class;
        }

        @Override
        public Type getOwnerType() {
            return null;
        }
    }


    /**
     * MD5加密
     *
     * @param data 明文字符串
     * @return 16进制密文
     */
    public static String encryptMD5ToString(final String data) {
        if (TextUtils.isEmpty(data)) {
            return "";
        }
        return encryptMD5ToString(data.getBytes());
    }

    /**
     * MD5加密
     *
     * @param data 明文字节数组
     * @return 16进制密文
     */
    public static String encryptMD5ToString(final byte[] data) {
        return bytes2HexString(encryptMD5(data));
    }

    private static String bytes2HexString(final byte[] bytes) {
        if (bytes == null) return null;
        int len = bytes.length;
        if (len <= 0) return null;
        char[] ret = new char[len << 1];
        for (int i = 0, j = 0; i < len; i++) {
            ret[j++] = hexDigits[bytes[i] >>> 4 & 0x0f];
            ret[j++] = hexDigits[bytes[i] & 0x0f];
        }
        return new String(ret);
    }

    private static final char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};

    /**
     * MD5加密
     *
     * @param data 明文字节数组
     * @return 密文字节数组
     */
    public static byte[] encryptMD5(final byte[] data) {
        return hashTemplate(data, "MD5");
    }

    /**
     * hash加密模板
     *
     * @param data      数据
     * @param algorithm 加密算法
     * @return 密文字节数组
     */
    private static byte[] hashTemplate(final byte[] data, final String algorithm) {
        if (data == null || data.length <= 0) return null;
        try {
            MessageDigest md = MessageDigest.getInstance(algorithm);
            md.update(data);
            return md.digest();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            return null;
        }
    }

    public static String getNowDate() {
        Date date = new Date();//获取时间
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");//转换格式
        return sdf.format(date);
    }


    public static Long getDistanceTime(long now, long last) {
        Long s = (now - last) / (1000 * 60);
        return s;
    }

    public static boolean isYesterday(long time) {
        if (time == 0) {
            return true;
        }
        boolean isYesterday = false;
        Date date;
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            date = sdf.parse(sdf.format(new Date()));
            if (time < date.getTime() && time > (date.getTime() - 24 * 60 * 60 * 1000)) {
                isYesterday = true;
            }
        } catch (ParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return isYesterday;
    }

    public static String getYesterday() {
        Date date = new Date();//取时间
        Calendar calendar = new GregorianCalendar();
        calendar.setTime(date);
        calendar.add(calendar.DATE, -1);//把日期往前减少一天，若想把日期向后推一天则将负数改为正数
        date = calendar.getTime();
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
        String dateString = formatter.format(date);
        return dateString;
    }

    /**
     * 获取手机型号
     *
     * @return 手机型号
     */
    public static String getSystemModel() {
        return android.os.Build.MODEL;
    }


    public static String getSystemProperty(String propName) {
        String line;
        BufferedReader input = null;
        try {
            Process p = Runtime.getRuntime().exec("getprop " + propName);
            input = new BufferedReader(new InputStreamReader(p.getInputStream()), 1024);
            line = input.readLine();
            input.close();
        } catch (IOException ex) {
            return null;
        } finally {
            if (input != null) {
                try {
                    input.close();
                } catch (IOException e) {
                }
            }
        }
        return line;
    }

    /**
     * @param bitmap
     * @param roundPx 一般设成14
     * @return
     * @Description: 获得圆角图片的方法
     * @author
     * @date 2014-4-2
     */
    public static Bitmap getRoundedCornerBitmap(Bitmap bitmap, float roundPx) {
        if (bitmap == null) {
            return null;
        }
        try {
            Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
                    bitmap.getHeight(), Bitmap.Config.ARGB_8888);
            Canvas canvas = new Canvas(output);
            final int color = 0xff424242;// 颜色值（0xff---alpha）
            final Paint paint = new Paint();
            final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
            final RectF rectF = new RectF(rect);// Rect是使用int类型作为数值，RectF是使用float类型作为数值
            // --------抗锯齿-------//
            paint.setAntiAlias(true);
            canvas.drawARGB(0, 0, 0, 0);
            paint.setColor(color);
            canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
            paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
            canvas.drawBitmap(bitmap, null, rect, paint);
            return output;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 获取application中指定的meta-data 调用方法时key就是UMENG_CHANNEL
     *
     * @return 如果没有获取成功(没有对应值 ， 或者异常)，则返回值为空
     */
    public static String getChannel(Context ctx) {
        if (ctx == null || TextUtils.isEmpty("UMENG_CHANNEL")) {
            return null;
        }
        String resultData = null;
        try {
            PackageManager packageManager = ctx.getPackageManager();
            if (packageManager != null) {
                ApplicationInfo applicationInfo = packageManager.getApplicationInfo(ctx.getPackageName(), PackageManager.GET_META_DATA);
                if (applicationInfo != null) {
                    if (applicationInfo.metaData != null) {
                        resultData = applicationInfo.metaData.getString("UMENG_CHANNEL");
                    }
                }

            }
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }

        return resultData;
    }

    /**
     * 将Map转化为Json字符串
     *
     * @param map
     * @return String
     */
    public static <T> String mapToJson(Map<String, T> map) {
        Gson gson = new Gson();
        String jsonStr = gson.toJson(map);
        return jsonStr;
    }

    public static boolean isLogin(boolean isStart) {
        String token = SettingPreference.getUserToken();
        if (TextUtils.isEmpty(token)) {
            if (isStart) {
                Intent intent = Constant.Param.isLocal ? RounterBus.getRounter(RounterApi.class).getIntentActivityLocalLogin() : RounterBus.getRounter(RounterApi.class).getIntentActivityLogin();
                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                AppContext.get().startActivity(intent);
            }
            return false;
        }
        return true;
    }


    public static AlertDialog.Builder createAlertDialog(Context context) {
        AlertDialog.Builder builder = new AlertDialog.Builder(context);
        builder.setIconAttribute(android.R.attr.alertDialogIcon);
        return builder;
    }


    // 判断是否缺少权限
    public static boolean needsPermission(String permission) {
        return ContextCompat.checkSelfPermission(AppContext.get(), permission) != PackageManager.PERMISSION_GRANTED;
    }

    //判断系统是否设置了默认浏览器
    public static boolean hasPreferredApplication(Context context, Intent intent) {
        PackageManager pm = context.getPackageManager();
        ResolveInfo info = pm.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY);
        return !"android".equals(info.activityInfo.packageName);
    }

    /**
     * 判断当前是否是主进程
     *
     * @param context 上下文对象，用于获取包名
     * @return 如果取不到进程名或进程名与包名相同，则返回true
     */
    private static String sProcessName;
    private static boolean sIsMainProcess;

    public static boolean isMainProcess(Context context) {
        if (sProcessName == null) { // 如果上一次没获取到进程名，才重复获取
            // 获取当前进程名
            sProcessName = getProcessNameByAm(context);
            if (sProcessName == null) {
                sProcessName = getProcessNameFromFile(android.os.Process.myPid());
            }
            // 获取当前包名
            String packageName = context.getPackageName();
            sIsMainProcess = sProcessName == null || sProcessName.equals(packageName);
            LogUtils.d("Process", "主进程判断结果 = " + sIsMainProcess);
        }
        return sIsMainProcess;
    }

    /**
     * 通过ActivityManager获取当前进程名称
     *
     * @param context
     * @return 如果没获取到，则返回null
     */
    private static String getProcessNameByAm(Context context) {
        android.app.ActivityManager am = ((android.app.ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE));
        List<android.app.ActivityManager.RunningAppProcessInfo> processInfos = am.getRunningAppProcesses();
        if (processInfos != null) {
            int myPid = android.os.Process.myPid();
            for (android.app.ActivityManager.RunningAppProcessInfo info : processInfos) {
                if (info.pid == myPid) {
                    LogUtils.d("Process", "通过AM获取到进程 " + myPid + " 为 " + info.processName);
                    return info.processName;
                }
            }
        }
        LogUtils.d("Process", "没有通过AM获取到进程名");
        return null;
    }

    /**
     * 从proc下的文件里面获取进程号对应的进程名<br/>
     * 参考自https://bugly.qq.com/docs/user-guide/instruction-manual-android/?v=20161219153020
     *
     * @param pid 进程号
     * @return 进程名
     */
    private static String getProcessNameFromFile(int pid) {
        BufferedReader reader = null;
        try {
            reader = new BufferedReader(new FileReader("/proc/" + pid + "/cmdline"));
            String processName = reader.readLine();
            if (!TextUtils.isEmpty(processName)) {
                processName = processName.trim();
                LogUtils.d("Process", "通过File获取到进程 " + pid + " 为 " + processName);
            }
            return processName;
        } catch (Throwable throwable) {
            throwable.printStackTrace();
            LogUtils.d("Process", "判断进程失败", throwable);
        } finally {
            try {
                if (reader != null) {
                    reader.close();
                }
            } catch (IOException exception) {
                exception.printStackTrace();
                LogUtils.d("Process", "判断进程关闭文件失败", exception);
            }
        }
        return null;
    }

    public static void reflex(final TabLayout tabLayout, final int dp) {
        //了解源码得知 线的宽度是根据 tabView的宽度来设置的
        tabLayout.post(new Runnable() {
            @Override
            public void run() {
                try {
                    //拿到tabLayout的mTabStrip属性
                    LinearLayout mTabStrip = (LinearLayout) tabLayout.getChildAt(0);

                    int dp10 = Utils.dip2px(dp);

                    for (int i = 0; i < mTabStrip.getChildCount(); i++) {
                        View tabView = mTabStrip.getChildAt(i);

                        //拿到tabView的mTextView属性  tab的字数不固定一定用反射取mTextView
                        Field mTextViewField = tabView.getClass().getDeclaredField("textView");
                        mTextViewField.setAccessible(true);

                        TextView mTextView = (TextView) mTextViewField.get(tabView);

                        tabView.setPadding(0, 0, 0, 0);

                        //因为我想要的效果是   字多宽线就多宽，所以测量mTextView的宽度
                        int width = 0;
                        width = mTextView.getWidth();
                        if (width == 0) {
                            mTextView.measure(0, 0);
                            width = mTextView.getMeasuredWidth();
                        }

                        //设置tab左右间距为10dp  注意这里不能使用Padding 因为源码中线的宽度是根据 tabView的宽度来设置的
                        LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) tabView.getLayoutParams();
                        params.width = width;
                        params.leftMargin = dp10;
                        params.rightMargin = dp10;
                        tabView.setLayoutParams(params);

                        tabView.invalidate();
                    }

                } catch (NoSuchFieldException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        });
    }

    public static void setIndicator(TabLayout tabs, int leftDip, int rightDip, int bottomDip) {
        Class<?> tabLayout = tabs.getClass();
        Field tabStrip = null;
        try {
            tabStrip = tabLayout.getDeclaredField("slidingTabIndicator");
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
            return;
        }
        tabStrip.setAccessible(true);
        LinearLayout llTab = null;
        try {
            llTab = (LinearLayout) tabStrip.get(tabs);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
            return;
        }

        int left = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, leftDip, Resources.getSystem().getDisplayMetrics());
        int right = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, rightDip, Resources.getSystem().getDisplayMetrics());
        int bottom = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, bottomDip, Resources.getSystem().getDisplayMetrics());

        for (int i = 0; i < llTab.getChildCount(); i++) {

            View child = llTab.getChildAt(i);
            child.setPadding(0, 0, 0, 0);
            LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.MATCH_PARENT, 1);
            params.leftMargin = left;
            params.rightMargin = right;
            params.bottomMargin = bottom;
            child.setLayoutParams(params);
            child.invalidate();
        }
    }


    public static String getNewsApiUrl(int pgnum, int tabid, String preId, String postId, String preTs, String postTs) {
        int newsnum;
        if (Integer.valueOf(pgnum) <= 1) {
            newsnum = 4;
        } else {
            newsnum = 10;
        }
        String url = NetConfig.BASE_URL + NetConfig.News.URL_NEWS_URL + "?pgnum=" + pgnum + "&tabid=" + tabid + "&newsnum=" + newsnum;
        if (!TextUtils.isEmpty(preId)) {
            url += "&preId=" + preId;
        }
        if (!TextUtils.isEmpty(postId)) {
            url += "&postId=" + postId;
        }
        if (!TextUtils.isEmpty(preTs)) {
            url += "&preTs=" + preTs;
        }
        if (!TextUtils.isEmpty(postTs)) {
            url += "&postTs=" + postTs;
        }
        return url;
    }

    public static String getNewsEasternUrl(String type, String num, String startkey, String newkey) {
        long ts = System.currentTimeMillis();
        int newsNum = 10;

        if (TextUtils.isEmpty(startkey)) {
            startkey = "";
        }
        if (TextUtils.isEmpty(newkey)) {
            newkey = "";
        }
        if (Integer.valueOf(num) <= 1) {
            newsNum = 4;
        } else {
            newsNum = 10;
        }
        String sbts = String.valueOf(ts).substring(0, 8);
        String key = Constant.Key.DFTT_KEY;
        String qid = Constant.Key.DFTT_APP_ID;
        String imei = Constant.Param.ime;
        String deviceid = Constant.Param.androidId;
        String os = "android";
        String code = PhoneUtils.INSTANCE.getMd5Value(sbts + ":" + imei + ":" + qid + ":" + key).substring(8, 24);
        if (TextUtils.isEmpty(startkey)) {
            return NetConfig.News.URL_NEWS_DFURL + "?" + "ts=" + ts + "&key=" + key + "&code=" + code + "&type=" + type + "&qid=" + qid + "&ime=" + imei + "&pgnum=" + num + "&appver=" + PhoneUtils.INSTANCE.getAppVersionName(AppContext.get()) + "&deviceid=" + deviceid + "&os=" + os + "&newsnum=" + newsNum;
        } else {
            return NetConfig.News.URL_NEWS_DFURL + "?" + "ts=" + ts + "&key=" + key + "&code=" + code + "&type=" + type + "&qid=" + qid + "&ime=" + imei + "&startkey=" + startkey + "&newkey=" + newkey + "&pgnum=" + num + "&appver=" + PhoneUtils.INSTANCE.getAppVersionName(AppContext.get()) + "&deviceid=" + deviceid + "&os=" + os + "&newsnum=" + newsNum;
        }
    }

    public static String getNewsImeiUrl() {
        String qid = Constant.Key.DFTT_APP_ID;
        String imei = Base64.encodeToString(Constant.Param.imei.getBytes(), Base64.DEFAULT);

        return NetConfig.News.URL_NEWS_IMEI_URL + "?appqid=" + qid + "&idfa=" + imei;
    }


    public static Bitmap getLocalBitmap(String url) {
        try {
            FileInputStream fis = new FileInputStream(url);
            BitmapFactory.Options options = new BitmapFactory.Options();
            options.inJustDecodeBounds = false;
            options.inSampleSize = 1;
            Bitmap btp = BitmapFactory.decodeStream(fis, null, options);
            return btp;  ///把流转化为Bitmap图片

        } catch (FileNotFoundException e) {
            e.printStackTrace();
            return null;
        }

    }

    /**
     * 判断服务是否开启
     *
     * @return
     */
    public static boolean isServiceRunning(Context context, String ServiceName) {
        if (TextUtils.isEmpty(ServiceName)) {
            return false;
        }
        android.app.ActivityManager myManager = (android.app.ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
        List<android.app.ActivityManager.RunningServiceInfo> runningService = myManager.getRunningServices(30);
        for (int i = 0; i < runningService.size(); i++) {
            if (TextUtils.equals(runningService.get(i).service.getClassName().toString(), ServiceName)) {
                return true;
            }
        }
        return false;
    }

    public static String getTopPacketName() {
        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) {
            boolean useGranted = isUseGranted();
            LogUtils.e("TopAppService", "use 权限 是否允许授权=" + useGranted);
            if (useGranted) {
                String topApp = getHigherPackageName();
                LogUtils.e("TopAppService", "顶层app=" + topApp);
                return topApp;
            } else {
                //开启应用授权界面
//                Intent intent = new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS);
//                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
//                Appli.getContext().startActivity(intent);
                return "";
            }
        } else {
            String topApp = getLowerVersionPackageName();
            LogUtils.e("TopAppService", "顶层app=" + topApp);
            return topApp;
        }
    }

    /**
     * 判断  用户查看使用情况的权利是否给予app
     *
     * @return
     */
    public static boolean isUseGranted() {
        Context appContext = AppContext.get();
        AppOpsManager appOps = null;
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
            appOps = (AppOpsManager) appContext
                    .getSystemService(Context.APP_OPS_SERVICE);
        }
        int mode = -1;
        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) {
            mode = appOps.checkOpNoThrow("android:get_usage_stats",
                    android.os.Process.myUid(), appContext.getPackageName());
        }
        boolean granted = mode == AppOpsManager.MODE_ALLOWED;
        return granted;
    }

    /**
     * 高版本：获取顶层的activity的包名
     *
     * @return
     */
    public static String getHigherPackageName() {
        String topPackageName = "";
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            UsageStatsManager mUsageStatsManager = (UsageStatsManager) AppContext.get().getSystemService(Context.USAGE_STATS_SERVICE);
            long time = System.currentTimeMillis();
            //time - 1000 * 1000, time 开始时间和结束时间的设置，在这个时间范围内 获取栈顶Activity 有效
            List<UsageStats> stats = mUsageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_DAILY, time - 1000 * 1000, time);
            // Sort the stats by the last time used
            if (stats != null) {
                SortedMap<Long, UsageStats> mySortedMap = new TreeMap<>();
                for (UsageStats usageStats : stats) {
                    mySortedMap.put(usageStats.getLastTimeUsed(), usageStats);
                }
                if (mySortedMap != null && !mySortedMap.isEmpty()) {
                    topPackageName = mySortedMap.get(mySortedMap.lastKey()).getPackageName();
                    LogUtils.e("TopPackage Name", topPackageName);
                }
            }
        } else {
            android.app.ActivityManager activityManager = (android.app.ActivityManager) AppContext.get().getSystemService(Context.ACTIVITY_SERVICE);
            ComponentName topActivity = activityManager.getRunningTasks(1).get(0).topActivity;
            topPackageName = topActivity.getPackageName();
        }
        return topPackageName;
    }

    /**
     * 低版本：获取栈顶app的包名
     *
     * @return
     */
    public static String getLowerVersionPackageName() {
        String topPackageName;//低版本  直接获取getRunningTasks
        android.app.ActivityManager activityManager = (android.app.ActivityManager) AppContext.get().getSystemService(Context.ACTIVITY_SERVICE);
        ComponentName topActivity = activityManager.getRunningTasks(1).get(0).topActivity;
        topPackageName = topActivity.getPackageName();
        return topPackageName;
    }

    public static String getBase64(byte[] str) {
        String result = "";
        if (str != null) {
            try {
                result = new String(Base64.encode(str, Base64.NO_WRAP), "utf-8");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }
        return result;
    }

    //判断app是否安装
    public static Boolean isInstall(Intent intent) {
        return AppContext.get().getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY).size() > 0;
    }

    /**
     * 判断是否是debug模式
     *
     * @param context
     * @return
     */
    public static void checkDebugMode(Context context) {
        NetConfig.setBase_Url(SettingPreference.getCurrentEnv(context));
    }


    public static void onExit(Activity context) {
        context.finish();
        ActivityManager.getInstance().finishAllActivity();
        android.os.Process.killProcess(android.os.Process.myPid());
    }

    /*** 发送短信* @param smsBody*/
    public static void sendSMS(String smsBody) {
        Uri smsToUri = Uri.parse("smsto:");
        Intent intent = new Intent(Intent.ACTION_SENDTO, smsToUri);
        intent.putExtra("sms_body", smsBody);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        AppContext.get().startActivity(intent);
    }

    public static List<String> deCode(List<String> list) {
        List<String> data = new ArrayList<>();
        for (String str : list) {
            try {
                data.add(URLDecoder.decode(str, "utf-8"));
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }
        return data;
    }

    public static void setTime(long time, TextView text) {
        if (text == null) {
            return;
        }
        long totalSeconds = time / 1000;
        long seconds = totalSeconds % 60;
        long minutes = totalSeconds / 60 % 60;
//        val hours = totalSeconds / 3600
        String minutesStr = minutes < 10 ? "0" + minutes : minutes + "";
        String secondsStr = seconds < 10 ? "0" + seconds : seconds + "";

        text.setText(minutesStr + ":" + secondsStr);
    }

    public static String timeConversion(int time) {
        int hour = 0;
        int minutes = 0;
        int sencond = 0;
        int temp = time % 3600;
        if (time > 3600) {
            hour = time / 3600;
            if (temp != 0) {
                if (temp > 60) {
                    minutes = temp / 60;
                    if (temp % 60 != 0) {
                        sencond = temp % 60;
                    }
                } else {
                    sencond = temp;
                }
            }
        } else {
            minutes = time / 60;
            if (time % 60 != 0) {
                sencond = time % 60;
            }
        }
        return (hour<10?("0"+hour):hour) + ":" + (minutes<10?("0"+minutes):minutes) + ":" + (sencond<10?("0"+sencond):sencond);
    }

    public static String timeConversion2(int time) {
        int hour = 0;
        int minutes = 0;
        int sencond = 0;
        int temp = time % 3600;
        if (time > 3600) {
            hour = time / 3600;
            if (temp != 0) {
                if (temp > 60) {
                    minutes = temp / 60;
                    if (temp % 60 != 0) {
                        sencond = temp % 60;
                    }
                } else {
                    sencond = temp;
                }
            }
        } else {
            minutes = time / 60;
            if (time % 60 != 0) {
                sencond = time % 60;
            }
        }
        return (minutes<10?("0"+minutes):minutes) + ":" + (sencond<10?("0"+sencond):sencond);
    }

    public static boolean isShouldHideInput(View v, MotionEvent event) {
        if (v != null && (v instanceof EditText)) {
            int[] leftTop = {0, 0};
            //获取输入框当前的location位置
            v.getLocationInWindow(leftTop);
            int left = leftTop[0];
            int top = leftTop[1];
            int bottom = top + v.getHeight();
            int right = left + v.getWidth();
            if (event.getX() > left && event.getX() < right
                    && event.getY() > top && event.getY() < bottom) {
                // 点击的是输入框区域，保留点击EditText的事件
                return false;
            } else {
                return true;
            }
        }
        return false;
    }

    public static void setTouchMacro(View v, MotionEvent event, NewsEntity data) {
        if (data.getOpentype() == NewsEntity.AD_TYPE_API) {
            if (event.getAction() == MotionEvent.ACTION_DOWN) {
                data.setClickDownX(event.getX() + "");
                data.setClickDownY(event.getY() + "");

                data.setClickViewDownX(event.getX() + "");
                data.setClickViewDownY((event.getY() - v.getHeight()) + "");

            } else if (event.getAction() == MotionEvent.ACTION_UP) {
                data.setClickUpX(event.getX() + "");
                data.setClickUpY(event.getY() + "");

                data.setClickViewUpX(event.getX() + "");
                data.setClickViewUpY((event.getY() - v.getHeight()) + "");
            }
        }
    }

    /**
     * 清除WebView缓存
     */
    public static void clearWebViewCache(Context context) {
        //清理Webview缓存数据库
        try {
            context.deleteDatabase("webview.db");
            context.deleteDatabase("webviewCache.db");
        } catch (Exception e) {
            e.printStackTrace();
        }

        //WebView 缓存文件
        File appCacheDir = new File(FileUtils.INSTANCE.getWebViewCacheDiectory());

        File webviewCacheDir = new File(context.getCacheDir().getAbsolutePath() + "/webviewCache");

        //删除webview 缓存目录
        if (webviewCacheDir.exists()) {
            context.deleteFile(context.getCacheDir().getAbsolutePath() + "/webviewCache");
        }
        //删除webview 缓存 缓存目录
        if (appCacheDir.exists()) {
            context.deleteFile(FileUtils.INSTANCE.getWebViewCacheDiectory());
        }
    }

    /**
     * 跳转到应用商店评分
     *
     * @param context
     * @param myAppPkg
     * @param shopPkg
     */
    public static void goAppShop(Context context, String myAppPkg, String shopPkg) {
        if (TextUtils.isEmpty(myAppPkg)) {
            return;
        }

        try {
            Uri uri = Uri.parse("market://details?id=" + myAppPkg);
            Intent intent = new Intent(Intent.ACTION_VIEW, uri);
            if (!TextUtils.isEmpty(shopPkg)) {
                intent.setPackage(shopPkg);
            }
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            context.startActivity(intent);
        } catch (Exception e) {
            // 如果没有该应用商店，则显示系统弹出的应用商店列表供用户选择
            if (TextUtils.equals(shopPkg, "com.tencent.android.qqdownloader")) {
                Intent intent = new Intent();
                intent.setAction("android.intent.action.VIEW");
                Uri content_url = Uri.parse("https://android.myapp.com/myapp/detail.htm?apkName=" + Constant.Param.mPacketName);
                intent.setData(content_url);
                context.startActivity(intent);
            } else {
                goAppShop(context, myAppPkg, "com.tencent.android.qqdownloader");
            }
        }
    }

    public static void addHistory(NewsHistoryEntity data) {
        DataSupport.insert(DBConfig.NEWS_READ_HISTORY_TABLE_NAME);
        ContentValues value = new ContentValues();
        value.put(DBConfig.CONTENT, Utils.obj2Str(data));
        value.put(DBConfig.CONTENTID, "history");
        DataSupport.insert(DBConfig.NEWS_READ_HISTORY_TABLE_NAME)
                .withValue(value).withCallback(new DBCallback<String>() {
            @Override
            public void onResult(int code, String result) {
                LogUtils.d("history", "insert  code:" + code + "  result:" + result);
            }
        }).excute();
    }


    // 判断权限集合
    public static boolean needPermissions(String... permissions) {
        boolean isNeed;
        for (String permission : permissions) {
            isNeed = needsPermission(permission);
            if (isNeed) {
                return true;
            }
        }
        return false;
    }

    public static List<String> noPermissions(String... permissions) {
        List<String> list = new ArrayList<>();
        for (String permission : permissions) {
            if (needPermissions(permission)) {
                list.add(permission);
            }
        }
        return list;
    }

    public static String replaceAll(String str) {
        return str.replaceAll("[^a-z^A-Z]", "");
    }


    public static String md5(String string) {
        if (TextUtils.isEmpty(string)) {
            return "";
        }
        MessageDigest md5 = null;
        try {
            md5 = MessageDigest.getInstance("MD5");
            byte[] bytes = md5.digest(string.getBytes());
            StringBuilder result = new StringBuilder();
            for (byte b : bytes) {
                String temp = Integer.toHexString(b & 0xff);
                if (temp.length() == 1) {
                    temp = "0" + temp;
                }
                result.append(temp);
            }
            return result.toString();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return "";
    }

    public static Boolean isMember() {
        UserInfo userInfo = SettingPreference.getUserInfoData();
        if (userInfo == null) {
            Utils.showToast(AppContext.get(), "请先进行登录");
            return false;
        }
        if (TextUtils.equals(userInfo.memberType, "0")) {
            return false;
        } else {
            return true;
        }
    }

    public static void setOnScrollBottomListener(RecyclerView mRecyclerView, AdCallback<Integer> callback) {
        mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);
                if (newState == RecyclerView.SCROLL_STATE_DRAGGING) {
//                    RxBus.get().post(Constant.HIDE_MAIN_FLOAT_ICON, true);
                }
//                if (newState == RecyclerView.SCROLL_STATE_IDLE && isBottom(mRecyclerView)) {
//                    mPresenter.getNewsData(3);
//                }
            }

            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);
                //得到当前显示的最后一个item的view
                View lastChildView = recyclerView.getLayoutManager().getChildAt(recyclerView.getLayoutManager().getChildCount() - 1);
                //得到lastChildView的bottom坐标值
                if (lastChildView != null) {
                    int lastChildBottom = lastChildView.getBottom();
                    //得到Recyclerview的底部坐标减去底部padding值，也就是显示内容最底部的坐标
                    int recyclerBottom = recyclerView.getBottom() - recyclerView.getPaddingBottom();
                    //通过这个lastChildView得到这个view当前的position值
                    int lastPosition = recyclerView.getLayoutManager().getPosition(lastChildView);

                    //判断lastChildView的bottom值跟recyclerBottom
                    //判断lastPosition是不是最后一个position
                    //如果两个条件都满足则说明是真正的滑动到了底部
                    Log.d("onScrolled", "lastChildBottom:" + lastChildBottom);
                    Log.d("onScrolled", "recyclerBottom:" + recyclerBottom);
                    Log.d("onScrolled", "lastPosition:" + lastPosition);
                    Log.d("onScrolled", "recyclerView.getLayoutManager().getItemCount() - 1:" + (recyclerView.getLayoutManager().getItemCount() - 1));
                    if (lastChildBottom == recyclerBottom && lastPosition == recyclerView.getLayoutManager().getItemCount() - 1) {
                        callback.onResult(0, 0);
                    }
                }
            }
        });
    }
    public static boolean isSlideToBottom(RecyclerView recyclerView) {
        if (recyclerView == null) return false;
        if (recyclerView.computeVerticalScrollExtent() + recyclerView.computeVerticalScrollOffset() >= recyclerView.computeVerticalScrollRange())
            return true;
        return false;
    }

    /**
     * 乘法运算
     * @param m1
     * @param m2
     * @return
     */
    public static double mul(double m1, double m2,int m3) {
        BigDecimal p1 = new BigDecimal(Double.toString(m1));
        BigDecimal p2 = new BigDecimal(Double.toString(m2));
        BigDecimal p3 = new BigDecimal(Double.toString(m3));
        return p1.multiply(p2).multiply(p3).setScale(2, RoundingMode.HALF_UP).doubleValue();
    }
    /**
     * 提供精确的减法运算。
     * @param v1 被减数
     * @param v2 减数
     * @return 两个参数的差
     */
    public static double sub(double v1,double v2){
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.subtract(b2).doubleValue();
    }

    /**
     * 对入参保留最多两位小数(舍弃末尾的0)，如:
     * 3.345->3.34
     * 3.40->3.4
     * 3.0->3
     */
    public static String getNoMoreThanTwoDigits(double number) {
        DecimalFormat format = new DecimalFormat("0.##");
        //未保留小数的舍弃规则，RoundingMode.FLOOR表示直接舍弃。
        format.setRoundingMode(RoundingMode.FLOOR);
        return format.format(number);
    }

}

