/*
 * 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.
 */
package org.apache.weex.utils;

import android.annotation.SuppressLint;
import android.app.Application;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.os.Build;
import android.text.TextUtils;
import org.apache.weex.IWXStatisticsListener;
import org.apache.weex.WXEnvironment;
import org.apache.weex.adapter.IWXSoLoaderAdapter;
import org.apache.weex.adapter.IWXUserTrackAdapter;
import org.apache.weex.common.WXErrorCode;
import dalvik.system.PathClassLoader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.Enumeration;
import java.util.Locale;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;


/**
 * Utility class for managing so library, including load native library and version management.
 * <ol>
 *   <li>Load library<br>
 *     It Will try to use {@link System#loadLibrary(String)} to load native library. If it successes,
 *     the Android Framework will be responsible for managing library and library version.
 *     If it fails in case of some ceratin armebi-v7a architecture device, it will try to extract
 *     native library from apk and copy it the data directory of the app. Then load it using
 *     {@link System#load(String)}.
 *     </li>
 *  <li>
 *       Version control for extracting native library from apk.
 *  </li>
 * </ol>
 */
public class WXSoInstallMgrSdk {

  final static String LOGTAG = "INIT_SO";
  //below is the CPU string types
  private final static String ARMEABI = "armeabi"; //default
  private final static String X86 = "x86";
  private final static String MIPS = "mips";
  private final static String STARTUPSO = "/libweexjsb.so";
  private final static String STARTUPSOANDROID15 = "/libweexjst.so";

  static Application mContext = null;
  private static IWXSoLoaderAdapter mSoLoader = null;
  private static IWXStatisticsListener mStatisticsListener = null;

  private static String mAbi = null;

  public static void init(Application c,
                          IWXSoLoaderAdapter loader,
                          IWXStatisticsListener listener) {
    mContext = c;
    mSoLoader = loader;
    mStatisticsListener = listener;
  }

  public static boolean isX86(){
    String cpuType = _cpuType();
    return cpuType.equalsIgnoreCase(X86);
  }

  public static boolean isCPUSupport(){
    String cpuType = _cpuType();
    return !cpuType.equalsIgnoreCase(MIPS);
  }

  /**
   * Load so library.
   *
   * If a library loader adapter exists, use this adapter to load library,
   * otherwise use {@link System#loadLibrary(String)} to load library.
   * If failed to load library, try to extract the so library and load it
   * from arembi in the .apk
   *
   * @param libName library name, like webp, not necessary to be libwep.so
   * @param version the version of the so library
   */
  public static boolean initSo(String libName, int version, IWXUserTrackAdapter utAdapter) {
    String cpuType = _cpuType();
    if (cpuType.equalsIgnoreCase(MIPS) ) {
      WXExceptionUtils.commitCriticalExceptionRT(null,
              WXErrorCode.WX_KEY_EXCEPTION_SDK_INIT,
              "initSo", "[WX_KEY_EXCEPTION_SDK_INIT_CPU_NOT_SUPPORT] for android cpuType is MIPS",
              null);
      return false;
    }

    // copy startup so
    if (WXEnvironment.CORE_SO_NAME.equals(libName)) {
      copyStartUpSo();
    }


    boolean InitSuc = false;
      try {
        // If a library loader adapter exists, use this adapter to load library
        // instead of System.loadLibrary.
        if (mSoLoader != null) {
          mSoLoader.doLoadLibrary("c++_shared");
        } else {
          System.loadLibrary("c++_shared");
        }
      } catch (Exception | Error e) {
        WXExceptionUtils.commitCriticalExceptionRT(null,
                WXErrorCode.WX_KEY_EXCEPTION_SDK_INIT,
                "initSo",
                        "load c++_shared failed Detail Error is: " +e.getMessage(),
                null);

        if(WXEnvironment.isApkDebugable()) {
          throw e;
        }
      }

      /**
       * Load library with {@link System#loadLibrary(String)}
       */
      try {
        // If a library loader adapter exists, use this adapter to load library
        // instead of System.loadLibrary.
        if (mSoLoader != null) {
          mSoLoader.doLoadLibrary(libName);
        } else {
          System.loadLibrary(libName);
        }

        InitSuc = true;
      } catch (Exception | Error e2) {
        if (cpuType.contains(ARMEABI) || cpuType.contains(X86)) {
          WXExceptionUtils.commitCriticalExceptionRT(null,
                  WXErrorCode.WX_KEY_EXCEPTION_SDK_INIT,
                  "initSo", libName + "[WX_KEY_EXCEPTION_SDK_INIT_CPU_NOT_SUPPORT] for android cpuType is " +cpuType +
                          "\n Detail Error is: " +e2.getMessage(),
                  null);
        }

        if(WXEnvironment.isApkDebugable()) {
          throw e2;
        }
        InitSuc = false;
      }

//      try {

//        if (!InitSuc) {
//
//          //File extracted from apk already exists.
//          if (isExist(libName, version)) {
//            boolean res = _loadUnzipSo(libName, version, utAdapter);
//            if (res) {
//              return res;
//            } else {
//              //Delete the corrupt so library, and extract it again.
//              removeSoIfExit(libName, version);
//            }
//          }
//
//          //Fail for loading file from libs, extract so library from so and load it.
//          if (cpuType.equalsIgnoreCase(MIPS)) {
//            return false;
//          } else {
//            try {
//              InitSuc = unZipSelectedFiles(libName, version, utAdapter);
//            } catch (IOException e2) {
//              e2.printStackTrace();
//            }
//          }
//
//        }
//      } catch (Exception | Error e) {
//        InitSuc = false;
//        e.printStackTrace();
//      }
  //  }
    return InitSuc;
  }

  private static File _desSoCopyFile(String soName) {
    String cpuType = _cpuType();
    String copyPath = WXEnvironment.copySoDesDir();
    if (TextUtils.isEmpty(copyPath)) {
      return null;
    }
    File desDir = new File(copyPath, soName + "/" + cpuType);
    return desDir;
  }

  /**
   * copyStartUpSo
   */
  @SuppressLint("SdCardPath")
  public static void copyStartUpSo() {
    try {
      // copy libjsb.so to cache/weex/jsb/cputype
      String pkgName = WXEnvironment.getApplication().getPackageName();
      String cacheFile = WXEnvironment.getApplication().getApplicationContext().getCacheDir().getPath();

      // cp weexjsb any way
      // if android api < 16 copy libweexjst.so else copy libweexjsb.so
      boolean pieSupport = true;
      File newfile;
      String startSoName = WXEnvironment.CORE_JSB_SO_NAME;
      String startSoPath = STARTUPSO;
      if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
        pieSupport = false;
        startSoName = WXEnvironment.CORE_JST_SO_NAME;
        startSoPath = STARTUPSOANDROID15;
      }

      final File copyPath = _desSoCopyFile(startSoName);
      if(!copyPath.exists()) {
        copyPath.mkdirs();
      }
      newfile = new File(copyPath, startSoPath);
      WXEnvironment.CORE_JSB_SO_PATH = newfile.getAbsolutePath();
      String jsb = WXEnvironment.getDefaultSettingValue(startSoName, "-1");
      if(newfile.exists() && TextUtils.equals(WXEnvironment.getAppVersionName(), jsb)) {
        // no update so skip copy
        return;
      }

      String path = "/data/data/" + pkgName + "/lib";
      if (cacheFile != null && cacheFile.indexOf("/cache") > 0) {
        path = cacheFile.replace("/cache", "/lib");
      }
      File oldfile = null;
      if (pieSupport) {
        oldfile = new File(path, STARTUPSO);
      } else {
        oldfile = new File(path , STARTUPSOANDROID15);
      }


      if (!oldfile.exists()) {
        try {
          String weexjsb = ((PathClassLoader) (WXSoInstallMgrSdk.class.getClassLoader())).findLibrary(startSoName);
          oldfile = new File(weexjsb);
        } catch (Throwable throwable) {
          // do nothing
        }
      }


      if(!oldfile.exists()) {
        String extractSoPath = WXEnvironment.extractSo();
        oldfile = new File(extractSoPath, STARTUPSO);
      }

      if (oldfile.exists()) {
        WXFileUtils.copyFile(oldfile, newfile);
      }
      WXEnvironment.writeDefaultSettingsValue(startSoName, WXEnvironment.getAppVersionName());
    } catch (Throwable e) {
      e.printStackTrace();
    }
  }

  public static void copyJssRuntimeSo(){
    boolean tryUseRunTimeApi = WXUtils.checkGreyConfig("wxapm","use_runtime_api","0");
    WXLogUtils.e("weex", "tryUseRunTimeApi ? "+ tryUseRunTimeApi);
    if (!tryUseRunTimeApi){
      return;
    }
    try {
      WXLogUtils.e("weex", "copyJssRuntimeSo: ");
      File toPath = _desSoCopyFile(WXEnvironment.CORE_JSS_SO_NAME);
      if(!toPath.exists()) {
        toPath.mkdirs();
      }
      File targetFile = new File(toPath,"libweexjss.so");

      /** 1. check so and versionCode. if update, then rm old jss.so(runtime) in pkg/libs, and copy new so from apk **/
      String keyVersionCode = "app_version_code_weex";
      String defaultSettingValue = WXEnvironment.getDefaultSettingValue(keyVersionCode, "-1");


      if (targetFile.exists()){
        if (!TextUtils.equals(WXEnvironment.getAppVersionName(),defaultSettingValue)){
          targetFile.delete();
        }else {
          WXEnvironment.CORE_JSS_SO_PATH= targetFile.getAbsolutePath();
          WXEnvironment.sUseRunTimeApi = true;
          WXLogUtils.e("weex", "copyJssRuntimeSo exist:  return");
          return;
        }
      }
      /** 2. copy jss(runtime) so **/
      String fromPath =  ((PathClassLoader) (WXSoInstallMgrSdk.class.getClassLoader())).findLibrary("weexjssr");
      if (TextUtils.isEmpty(fromPath)){
        return;
      }
      targetFile.createNewFile();
      WXFileUtils.copyFileWithException(new File(fromPath),targetFile);
      /**3. update flag **/
      WXEnvironment.CORE_JSS_SO_PATH= targetFile.getAbsolutePath();
      WXEnvironment.writeDefaultSettingsValue(keyVersionCode,WXEnvironment.getAppVersionName());
      WXEnvironment.sUseRunTimeApi = true;
      WXLogUtils.e("weex", "copyJssRuntimeSo: cp end and return ");
    }catch (Throwable e){
      e.printStackTrace();
      WXEnvironment.sUseRunTimeApi = false;
      WXLogUtils.e("weex", "copyJssRuntimeSo:  exception" + e);
    }
  }

  private static String _getFieldReflectively(Build build, String fieldName) {
    try {
      final Field field = Build.class.getField(fieldName);
      return field.get(build).toString();
    } catch (Exception ex) {
      return "Unknown";
    }
  }

  public static String _cpuType() {
    if(TextUtils.isEmpty(mAbi)) {
      try {
        mAbi = Build.CPU_ABI;
      }catch (Throwable e){
        e.printStackTrace();
        mAbi = ARMEABI;
      }
      if (TextUtils.isEmpty(mAbi)){
        mAbi = ARMEABI;
      }
      mAbi = mAbi.toLowerCase(Locale.ROOT);
    }
    return mAbi;
  }

  /**
   *
   * @param libName lib name
   * @param size  the right size of lib
   * @return true for valid  ; false for InValid
   */
  static boolean checkSoIsValid(String libName, long size) {
    Context context = mContext;
    if (null == context) {
      return false;
    }
    try{
      long start=System.currentTimeMillis();
      if(WXSoInstallMgrSdk.class.getClassLoader() instanceof PathClassLoader ) {

        String path = ((PathClassLoader) (WXSoInstallMgrSdk.class.getClassLoader())).findLibrary(libName);
        if(TextUtils.isEmpty(path) ){
          return false;
        }
        File file = new File(path);

        if (!file.exists() || size == file.length()) {
          WXLogUtils.w("weex so size check path :" + path+"   "+(System.currentTimeMillis() - start));
          return true;
        } else {
          return false;
        }
      }
    }catch(Throwable e ){
      WXExceptionUtils.commitCriticalExceptionRT(null,
              WXErrorCode.WX_KEY_EXCEPTION_SDK_INIT,
              "checkSoIsValid", "[WX_KEY_EXCEPTION_SDK_INIT_CPU_NOT_SUPPORT] for " +
                      "weex so size check fail exception :"+e.getMessage(),
              null);
      WXLogUtils.e("weex so size check fail exception :"+e.getMessage());
    }

    return true;
  }

  /**
   * Concatenate the path of the so library, including directory.
   * @param libName the raw name of the lib
   * @param version the version of the so library
   * @return the path of the so library
   */
  @SuppressLint("SdCardPath")
  static String _targetSoFile(String libName, int version) {
    Context context = mContext;
    if (null == context) {
      return "";
    }

    String path = "/data/data/" + context.getPackageName() + "/files";

    File f = context.getFilesDir();
    if (f != null) {
      path = f.getPath();
    }
    return path + "/lib" + libName + "bk" + version + ".so";

  }

  /**
   * Remove the so library if it had been extracted.
   * @param libName
   * @param version
   */
  static void removeSoIfExit(String libName, int version) {

    String file = _targetSoFile(libName, version);
    File a = new File(file);
    if (a.exists()) {
      a.delete();
    }

  }

  /**
   * Tell whether the so is extracted.
   */
  static boolean isExist(String libName, int version) {

    String file = _targetSoFile(libName, version);
    File a = new File(file);
    return a.exists();

  }


  /**
   * Load .so library
   */
  @SuppressLint("UnsafeDynamicallyLoadedCode")
  static boolean _loadUnzipSo(String libName,
                              int version,
                              IWXUserTrackAdapter utAdapter) {
    boolean initSuc = false;
    try {
      if (isExist(libName, version)) {
        // If a library loader adapter exists, use this adapter to load library
        // instead of System.load.
        if (mSoLoader != null) {
          mSoLoader.doLoad(_targetSoFile(libName, version));
        } else {
          System.load(_targetSoFile(libName, version));
        }
      }
      initSuc = true;
    } catch (Throwable e) {
      initSuc = false;
      WXExceptionUtils.commitCriticalExceptionRT(null,
              WXErrorCode.WX_KEY_EXCEPTION_SDK_INIT_CPU_NOT_SUPPORT,
              "_loadUnzipSo", "[WX_KEY_EXCEPTION_SDK_INIT_WX_ERR_COPY_FROM_APK] " +
                      "\n Detail Msg is : " +  e.getMessage(),
              null);
      WXLogUtils.e("", e);
    }
    return initSuc;
  }

  static boolean unZipSelectedFiles(String libName,
                                    int version,
                                    IWXUserTrackAdapter utAdapter) throws ZipException, IOException {
    String sourcePath = "lib/armeabi/lib" + libName + ".so";

    String zipPath = "";
    Context context = mContext;
    if (context == null) {
      return false;
    }

    ApplicationInfo aInfo = context.getApplicationInfo();
    if (null != aInfo) {
      zipPath = aInfo.sourceDir;
    }

    ZipFile zf;
    zf = new ZipFile(zipPath);
    try {

      for (Enumeration<?> entries = zf.entries(); entries.hasMoreElements(); ) {
        ZipEntry entry = ((ZipEntry) entries.nextElement());
        if (entry.getName().startsWith(sourcePath)) {

          InputStream in = null;
          FileOutputStream os = null;
          FileChannel channel = null;
          int total = 0;
          try {

            //Make sure the old library is deleted.
            removeSoIfExit(libName, version);

            //Copy file
            in = zf.getInputStream(entry);
            os = context.openFileOutput("lib" + libName + "bk" + version + ".so",
                    Context.MODE_PRIVATE);
            channel = os.getChannel();

            byte[] buffers = new byte[1024];
            int realLength;

            while ((realLength = in.read(buffers)) > 0) {
              //os.write(buffers);
              channel.write(ByteBuffer.wrap(buffers, 0, realLength));
              total += realLength;

            }
          } finally {
            if (in != null) {
              try {
                in.close();
              } catch (Exception e) {
                e.printStackTrace();
              }
            }

            if (channel != null) {
              try {
                channel.close();
              } catch (Exception e) {
                e.printStackTrace();
              }
            }

            if (os != null) {
              try {
                os.close();
              } catch (Exception e) {
                e.printStackTrace();
              }
            }

            if (zf != null) {
              zf.close();
              zf = null;
            }
          }

          if (total > 0) {
            return _loadUnzipSo(libName, version, utAdapter);
          } else {
            return false;
          }
        }
      }
    } catch (java.io.IOException e) {
      e.printStackTrace();
      WXExceptionUtils.commitCriticalExceptionRT(null,
              WXErrorCode.WX_KEY_EXCEPTION_SDK_INIT_CPU_NOT_SUPPORT,
              "unZipSelectedFiles", "[WX_KEY_EXCEPTION_SDK_INIT_unZipSelectedFiles] " +
                      "\n Detail msg is: " + e.getMessage(),
              null);

    } finally {

      if (zf != null) {
        zf.close();
        zf = null;
      }
    }
    return false;
  }

  /**
   * Using {@Code WXExceptionUtils.commitCriticalExceptionRT}  insted
   */
//  static void commit(IWXUserTrackAdapter utAdapter, String errCode, String errMsg) {
//    if (mStatisticsListener != null) {
//      mStatisticsListener.onException("0", errCode, errMsg);
//    }
//
//    if (utAdapter == null) {
//      return;
//    }
//    if (errCode != null && errMsg != null) {
//      WXPerformance p = new WXPerformance();
//      p.errCode = errCode;
//      p.errMsg = errMsg;
//      utAdapter.commit(null, null, WXEnvironment.ENVIRONMENT, p, null);
//    } else {
//      utAdapter.commit(null, null, WXEnvironment.ENVIRONMENT, null, null);
//
//    }
//  }

}
