package org.apache.cordova.logtofile;

import android.content.pm.ApplicationInfo;
import android.net.Uri;
import android.os.Environment;

import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaInterface;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.CordovaWebView;
import org.json.JSONArray;
import org.json.JSONException;
import org.slf4j.LoggerFactory;

import java.io.File;

import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.android.LogcatAppender;
import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.FileAppender;
import ch.qos.logback.core.util.StatusPrinter;

public class LogToFile extends CordovaPlugin {
    private static String LOGFILE_PATH;

    private static final org.slf4j.Logger log = LoggerFactory.getLogger(LogToFile.class);

    @Override
    public void initialize(CordovaInterface cordova, CordovaWebView webView) {
        super.initialize(cordova, webView);
    }

    private void configureLogger() {
        // reset the default context (which may already have been initialized)
        // since we want to reconfigure it
        LoggerContext lc = (LoggerContext)LoggerFactory.getILoggerFactory();
        lc.reset();

        // setup FileAppender
        PatternLayoutEncoder encoder = new PatternLayoutEncoder();
        encoder.setContext(lc);
        encoder.setPattern("%d{yyyy-dd-MM HH:mm:ss.SSS} : %-5level : %msg%n");
        encoder.start();

        FileAppender<ILoggingEvent> fileAppender = new FileAppender<ILoggingEvent>();
        fileAppender.setContext(lc);
        //fileAppender.setLazy(true);
        fileAppender.setAppend(true);
        fileAppender.setName("FILE");
        fileAppender.setFile(LOGFILE_PATH);
        fileAppender.setEncoder(encoder);
        fileAppender.start();

        LogcatAppender logcatAppender = new LogcatAppender();
        logcatAppender.setContext(lc);
        logcatAppender.setName("LOGCAT");
        logcatAppender.setEncoder(encoder);
        logcatAppender.start();

        // add the newly created appenders to the root logger;
        // qualify Logger to disambiguate from org.slf4j.Logger
        ch.qos.logback.classic.Logger root = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
        root.setLevel(Level.ALL);
        root.addAppender(fileAppender);
        root.addAppender(logcatAppender);

        StatusPrinter.print(lc);
    }

    private static String pathCombine(String path1, String path2) {
        File parent = new File(path1);
        File child = new File(parent, path2);
        return child.getPath();
    }

    @Override
    public boolean execute(String action, JSONArray data, final CallbackContext callbackContext) throws JSONException {
        if (action.equals("write")) {
            final String line = data.getString(0);
            cordova.getThreadPool().execute(new Runnable() {
                public void run() {
                    try {
                        log.debug(line);
                        callbackContext.success();
                    } catch (Exception e) {
                        callbackContext.error("Logger exception:" + e.toString());
                    }
                }
            });

        } else if (action.equals("info")) {
            final String line = data.getString(0);
            cordova.getThreadPool().execute(new Runnable() {
                public void run() {
                    try {
                        log.info(line);
                        callbackContext.success();
                    } catch (Exception e) {
                        callbackContext.error("Logger exception:" + e.toString());
                    }
                }
            });

        } else if (action.equals("warn")) {
            final String line = data.getString(0);
            cordova.getThreadPool().execute(new Runnable() {
                public void run() {
                    try {
                        log.warn(line);
                        callbackContext.success();
                    } catch (Exception e) {
                        callbackContext.error("Logger exception:" + e.toString());
                    }
                }
            });

        } else if (action.equals("error")) {
            final String line = data.getString(0);
            cordova.getThreadPool().execute(new Runnable() {
                public void run() {
                    try {
                        log.error(line);
                        callbackContext.success();
                    } catch (Exception e) {
                        callbackContext.error("Logger exception:" + e.toString());
                    }
                }
            });

        } else if (action.equals("setLogfilePath")) {
            final String logfilePath = data.getString(0);
            cordova.getThreadPool().execute(new Runnable() {
                public void run() {
                    try {
                        LOGFILE_PATH = pathCombine(Environment.getExternalStorageDirectory().getAbsolutePath(), logfilePath);
                        logConfigurator.setFileName(LOGFILE_PATH);
                        logConfigurator.setResetConfiguration(true);
                        logConfigurator.configure();
                        callbackContext.success(LOGFILE_PATH);
                    } catch (Exception e) {
                        Log.d(TAG, "Log exception:" + e.toString());
                        callbackContext.error("Log exception:" + e.toString());
                    }
                }
            });

        } else if (action.equals("getLogfilePath")) {
                cordova.getThreadPool().execute(new Runnable() {
                    public void run() {
                        try {
                            callbackContext.success(Uri.fromFile(new File(LOGFILE_PATH)).toString());
                        } catch (Exception e) {
                            callbackContext.error("Logger exception:" + e.toString());
                        }
                    }
                });

        } else {
            return false;
        }
        return true;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        // assume SLF4J is bound to logback-classic in the current environment
        LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
        loggerContext.stop();
    }

}

@@ -2769,32 +2769,263 @@
 tPath();%0A    %7D%0A%0A
+    private boolean isExternalStorageWritable() %7B%0A        String state = Environment.getExternalStorageState();%0A        if (Environment.MEDIA_MOUNTED.equals(state)) %7B%0A            return true;%0A        %7D%0A        return false;%0A    %7D%0A%0A
     @Override%0A  
@@ -3014,32 +3014,32 @@
 %0A%0A    @Override%0A
-
     public boole
@@ -3138,24 +3138,25 @@
 Exception %7B%0A
+%0A
         if (
@@ -3174,13 +3174,13 @@
 ls(%22
-write
+debug
 %22)) 
@@ -5339,32 +5339,95 @@
           try %7B%0A
+                        if (isExternalStorageWritable()) %7B%0A    
                 
@@ -5564,348 +5564,309 @@
     
-logC
+    c
 onfigur
-ator.setFileName(LOGFILE_PATH);%0A                        logConfigurator.setResetConfiguration(true);%0A                        logConfigurator.configure();%0A                        callbackContext.success(LOGFILE_PATH);%0A                    %7D catch (Exception e) %7B%0A                        Log.d(TAG, %22Log exception:%22 + e.toString());
+eLogger();%0A                            callbackContext.success(LOGFILE_PATH);%0A                        %7D else %7B%0A                            callbackContext.error(%22Logger config Error: External storage is not writable.%22);%0A                        %7D%0A                    %7D catch (Exception e) %7B
 %0A   
@@ -5912,16 +5912,19 @@
 ror(%22Log
+ger
  excepti

check if external storage is writable