package com.tomastc.bta500.lib;

import android.content.ContentResolver;
import android.content.Context;
import android.content.DialogInterface;
import android.util.Log;
import android.widget.Toast;

import androidx.documentfile.provider.DocumentFile;

import com.tomastc.bta500.MainActivity;
import com.tomastc.bta500.R;
import com.tomastc.bta500.SettingsActivity;
import com.tomastc.bta500.lib.common.AsyncFtpClient;
import com.tomastc.bta500.lib.common.AsyncHttpClient;
import com.tomastc.bta500.lib.common.FileUtil;
import com.tomastc.bta500.lib.common.MyAlertDialog;
import com.tomastc.bta500.lib.common.Utils;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

public class Settings {
    
    private static Context context;

    private static final String SETTING_PATH = "skt";
    private static final String LOG_PATH = "log";

    private static final String MANAGEMENT_INFO = "MngInfo.csv";
    private static final String SETTING_INFO = "Settings.csv";
    private static final String USER_INFO = "UserInfo.csv";

    private static Map<String, String> mgmtList = new HashMap<String, String>();
    private static Map<String, String> settingList = new HashMap<String, String>();
    private static Map<String, String> usrList = new HashMap<String, String>();
    private static List<UserLogin_list> user_login_list = new ArrayList<UserLogin_list>();

    private static UserInfo userInfoX;
    private static ShiftCode shiftCode;
    private static WorkShopNo workShopNo;

    private static WorkMode workMode;

    public enum WorkMode {
        COMPLETION(0)
        , NG_LABEL(1)
        , COMPONENT_DETAIL(2) // Version 1.4.0
        , COMPONENT_CHECK_PROGRESS(3) // Version 1.4.0
        , DIRECT_LABOR(4)// Version 1.6.0
        ;
        private final int id;

        WorkMode(final int id) {
            this.id = id;
        }

        public int getId() {
            return id;
        }

        public static Settings.WorkMode fromId(final int id) {
            for (Settings.WorkMode e : Settings.WorkMode.values()) {
                if (e.id == id) {
                    return e;
                }
            }
            return null;
        }
    }

    public static void readManagementFile(File dir) throws IOException {
        try {
            // clear list first
            mgmtList.clear();

            String raw = FileUtil.readFile(MANAGEMENT_INFO, dir.getAbsolutePath());

            String[] lines = raw.split(System.getProperty("line.separator"));
            int i = 0;
            for (String line : lines) {
                Log.d(Settings.context.getString(R.string.tag), "read line:" + line);
                String[] values = line.split(",");
                try {
                    mgmtList.put(values[0], values[1]);
                    i++;
                } catch (Exception e) {
                    Log.d(Settings.context.getString(R.string.tag), "line format error!");
                }
            }

            if (lines.length == 0 || i==0) {
                throw new IOException("file format error");
            }
        } catch (IOException ioe) {
            Log.d(Settings.context.getString(R.string.tag), "cannot read file, error:" + ioe.getMessage());
            throw ioe;
        }
    }

    public static void readManagementFile(DocumentFile path, ContentResolver contentResolver) {

        // read manager file
        Log.d(Settings.context.getString(R.string.tag), "open file:" + MANAGEMENT_INFO);
        DocumentFile mgmtFile = path.findFile(MANAGEMENT_INFO);
        if (mgmtFile.exists() && mgmtFile.canRead()) {
            try {
                String raw = FileUtil.readTextFromUri(mgmtFile.getUri(), contentResolver);
                Log.d(Settings.context.getString(R.string.tag), "file content:" + raw);

                String[] lines = raw.split(System.getProperty("line.separator"));
                for (String line : lines) {
                    String[] values = line.split("=");
                    mgmtList.put(values[0], values[1]);
                }
            } catch (IOException ioe) {
                Log.d(Settings.context.getString(R.string.tag), "cannot read file, error:" + ioe.getMessage());
            }
        } else {
            Log.i("SKT", "file not found![" + MANAGEMENT_INFO + "]");
        }

    }

    public static void readSettingFile(File dir) {
        try {
            // clear list first
            settingList.clear();

            String raw = FileUtil.readFile(SETTING_INFO, dir.getAbsolutePath());

            String[] lines = raw.split(System.getProperty("line.separator"));
            int i = 0;
            for (String line : lines) {
                Log.d(Settings.context.getString(R.string.tag), "read line:" + line);
                String[] values = line.split(",");
                try {
                    settingList.put(values[0], values[1]);
                    i++;
                } catch (Exception e) {
                    Log.d(Settings.context.getString(R.string.tag), "line format error!");
                }
            }

            if (lines.length == 0 || i==0) {
                throw new IOException("file format error");
            }
        } catch (IOException ioe) {
            Log.d(Settings.context.getString(R.string.tag), "cannot read file, error:" + ioe.getMessage());
        }
    }

    public static void readSettingFile(DocumentFile path, ContentResolver contentResolver) {

        // read setting file
        Log.d(Settings.context.getString(R.string.tag), "open file:" + SETTING_INFO);
        DocumentFile settingInfoFile = path.findFile(SETTING_INFO);
        if (settingInfoFile.exists() && settingInfoFile.canRead()) {
            try {
                String raw = FileUtil.readTextFromUri(settingInfoFile.getUri(), contentResolver);
                Log.d(Settings.context.getString(R.string.tag), "file content:" + raw);

                String[] lines = raw.split(System.getProperty("line.separator"));
                int i = 0;
                for (String line : lines) {
                    String[] values = line.split(",");
                    settingList.put(values[0], values[1]);
                }
            } catch (IOException ioe) {
                Log.d(Settings.context.getString(R.string.tag), "cannot read file, error:" + ioe.getMessage());
            }
        } else {
            Log.i("SKT", "file not found![" + SETTING_INFO + "]");
        }
    }

    public static void readUserInfoFile(File dir) throws IOException {
        try {
            // clear list first
            usrList.clear();

            String raw = FileUtil.readFile(USER_INFO, dir.getAbsolutePath());

            String[] lines = raw.split(System.getProperty("line.separator"));
            int i = 0;
            for (String line : lines) {
                Log.d(Settings.context.getString(R.string.tag), "read line:" + line);
                String[] values = line.split(",");
                try {
                    usrList.put(values[0], values[1]);
                    i++;
                } catch (Exception e) {
                    Log.d(Settings.context.getString(R.string.tag), "line format error!");
                }
            }

            if (lines.length == 0 || i==0) {
                throw new IOException("file format error");
            }
        } catch (IOException ioe) {
            Log.d(Settings.context.getString(R.string.tag), "cannot read file, error:" + ioe.getMessage());
            throw ioe;
        }
    }

    public static void readUserInfoFile(DocumentFile path, ContentResolver contentResolver) {

        // read user info file
        Log.d(Settings.context.getString(R.string.tag), "open file:" + USER_INFO);
        DocumentFile userInfoFile = path.findFile(USER_INFO);
        if (userInfoFile.exists() && userInfoFile.canRead()) {
            try {
                String raw = FileUtil.readTextFromUri(userInfoFile.getUri(), contentResolver);
                Log.d(Settings.context.getString(R.string.tag), "file content:" + raw);

                String[] lines = raw.split(System.getProperty("line.separator"));
                for (String line : lines) {
                    String[] values = line.split(",");
                    usrList.put(values[0], values[1]);
                }
            } catch (IOException ioe) {
                Log.d(Settings.context.getString(R.string.tag), "cannot read file, error:" + ioe.getMessage());
            }
        } else {
            Log.i("SKT", "file not found![" + USER_INFO + "]");
        }
    }

    public static void updateSettingsFile(Map<String, String> settingList, String path) {
        Settings.settingList = settingList;

        Log.d(Settings.context.getString(R.string.tag), "write settings file...");
        try {
            FileUtil.writeFile(SETTING_INFO, path, Utils.mapToCsv((HashMap) settingList));
        } catch (IOException ioe) {
            Log.d(Settings.context.getString(R.string.tag), "cannot write file, error:" + ioe.getMessage());
        }
    }

    public static void init(Context context) {
        Settings.context = context;
        
        readSettingFile(context.getFilesDir());

        String localDir = context.getFilesDir().getAbsolutePath();

        // load manager setting
        try {
            readManagementFile(context.getFilesDir());
        } catch (Exception ioe) {
            try {
                if (Settings.getServerMode().equalsIgnoreCase("http")) {
                    new AsyncHttpClient(
                            context
                            ,Settings.getServer() + "/" + Settings.getPath() + "/" + Settings.getManagementInfo()
                            , ""
                    ) {
                        @Override
                        public void onFinished(String response, int resp_code) {
                            Log.d(Settings.context.getString(R.string.tag), "response: " + response);
                            if (resp_code == 200) {
                                Log.d(Settings.context.getString(R.string.tag), "write management info file...");
                                try {
                                    FileUtil.writeFile(MANAGEMENT_INFO, context.getFilesDir().getAbsolutePath(), response);
                                } catch (IOException ioe) {
                                    Log.d(Settings.context.getString(R.string.tag), "cannot write file, error:" + ioe.getMessage());
                                }
                            }
                        }

                        @Override
                        protected void onError(Exception e) {

                        }
                    }
                            .execute();
                } else {
                    new AsyncFtpClient(new AsyncFtpClient.TaskListener() {
                        @Override
                        public void onFinished(String result) {
                            // Do Something after the task has finished
                            try {
                                readManagementFile(context.getFilesDir());
                            } catch (IOException e) {
                                Log.d(Settings.context.getString(R.string.tag), "read Manager file error");
                            }
                        }
                    }).execute(Settings.getServer(), Settings.getUser(), Settings.getPassword(),
                            AsyncFtpClient.ACTION.DOWNLOAD,
                            localDir + "/" + Settings.getManagementInfo(),
                            Settings.getSettingList().get("path") +
                                    "/" + Settings.getManagementInfo());

                }
            } catch (Exception e) {
                Log.d(Settings.context.getString(R.string.tag), "download file failed");
            }
        }

        // load user setting
        try {
            readUserInfoFile(context.getFilesDir());
        } catch (Exception ioe) {

            try {

                if (Settings.getServerMode().equalsIgnoreCase("http")) {
                    new AsyncHttpClient(
                            context
                            ,Settings.getServer() + "/" + Settings.getPath() + "/" + Settings.getUserInfo()
                            , ""
                    ) {
                        @Override
                        public void onFinished(String response, int resp_code) {
                            Log.d(Settings.context.getString(R.string.tag), "response: " + response);
                            if (resp_code == 200) {
                                Log.d(Settings.context.getString(R.string.tag), "write user info file...");
                                try {
                                    FileUtil.writeFile(USER_INFO, context.getFilesDir().getAbsolutePath(), response);
                                } catch (IOException ioe) {
                                    Log.d(Settings.context.getString(R.string.tag), "cannot write file, error:" + ioe.getMessage());
                                }
                            }
                        }

                        @Override
                        protected void onError(Exception e) {

                        }
                    }
                            .execute();
                } else {
                    new AsyncFtpClient(new AsyncFtpClient.TaskListener() {
                        @Override
                        public void onFinished(String result) {
                            // Do Something after the task has finished
                            try {
                                Toast.makeText(context, "Config files updated. Restart required!",
                                        Toast.LENGTH_LONG).show();
                                readUserInfoFile(context.getFilesDir());


                            } catch (IOException e) {
                                Log.d(Settings.context.getString(R.string.tag), "read User info file error");
                            }
                        }
                    }).execute(Settings.getServer(), Settings.getUser(), Settings.getPassword(),
                            AsyncFtpClient.ACTION.DOWNLOAD,
                            localDir + "/" + Settings.getUserInfo(),
                            Settings.getSettingList().get("path") +
                                    "/" + Settings.getUserInfo());
                }

            } catch (Exception e) {
                Log.d(Settings.context.getString(R.string.tag), "download file failed");
            }
        }
    }

    public static UserInfo getUserInfoX() {
        return userInfoX;
    }

    public static void setUserInfoX(UserInfo userInfoX) {
        Settings.userInfoX = userInfoX;
    }

    public static ShiftCode getShiftCode() {
        return shiftCode;
    }

    public static void setShiftCode(ShiftCode shiftCode) {
        Settings.shiftCode = shiftCode;
    }

    public static WorkShopNo getWorkShopNo() {
        return workShopNo;
    }

    public static void setWorkShopNo(WorkShopNo workShopNo) {
        Settings.workShopNo = workShopNo;
    }

    public static Map<String, String> getMgmtList() {
        return mgmtList;
    }

    public static Map<String, String> getSettingList() {
        return settingList;
    }

    public static void setSettingList(Map<String, String> settingList) {
        Settings.settingList = settingList;
    }

    public static Map<String, String> getUsrList() {
        return usrList;
    }

    public static void setUserLogin_list(List<UserLogin_list> user_login_list){
        Settings.user_login_list = user_login_list;
    }

    public static  List<UserLogin_list> getUserLogin_list(){
        return user_login_list;
    }

    public static String getDeviceNo() {
        return Settings.settingList.get("device_no");
    }

    public static void setDeviceNo(String device_no) {
        Settings.settingList.put("device_no", device_no);
    }

    public static String getSettingPath() {
        return SETTING_PATH;
    }

    public static String getLogPath() {
        return LOG_PATH;
    }

    public static String getServerMode() {
        return Settings.settingList.get("server_mode");
    }

    public static void setServerMode(String server_mode) {
        Settings.settingList.put("server_mode", server_mode);
    }

    public static String getServer() {
        return Settings.settingList.get("server");
    }

    public static void setServer(String server) {
        Settings.settingList.put("server", server);
    }

    public static String getUser() {
        return Settings.settingList.get("user");
    }

    public static void setUser(String user) {
        Settings.settingList.put("user", user);
    }

    public static String getPassword() {
        return Settings.settingList.get("password");
    }

    public static void setPassword(String password) {
        Settings.settingList.put("password", password);
    }

    public static String getPath() {
        return Settings.settingList.get("path");
    }

    public static void setPath(String path) {
        Settings.settingList.put("path", path);
    }

    public static String getManagementInfo() {
        return MANAGEMENT_INFO;
    }

    public static String getSettingInfo() {
        return SETTING_INFO;
    }

    public static String getUserInfo() {
        return USER_INFO;
    }

    public static WorkMode getWorkMode() {
        return workMode;
    }

    public static void setWorkMode(WorkMode workMode) {
        Settings.workMode = workMode;
    }

    public static void removeAllFile(File dir) {
        String[] filename_ = {
                Settings.getUserInfo(),
                Settings.getManagementInfo(),
                Settings.getSettingInfo()};
        for (String filename : filename_) {
            File file = new File(dir, filename);
            if (file.exists()) {
                if (file.delete()) {
                    Log.i(Settings.context.getString(R.string.tag), "file removed :" + filename);
                } else {
                    Log.i(Settings.context.getString(R.string.tag), "remove failed :" + filename);
                }
            }
        }
    }

    public static void removeAllFileExceptSettings(File dir) {
        String[] filename_ = {
                Settings.getUserInfo(),
                Settings.getManagementInfo()};
        for (String filename : filename_) {
            File file = new File(dir, filename);
            if (file.exists()) {
                if (file.delete()) {
                    Log.i(Settings.context.getString(R.string.tag), "file removed :" + filename);
                } else {
                    Log.i(Settings.context.getString(R.string.tag), "remove failed :" + filename);
                }
            }
        }
    }
}
