package com.its.vds.webapp.service;

import com.its.app.utils.OS;
import com.its.vds.webapp.vo.FileInfoVo;
import lombok.extern.slf4j.Slf4j;
import net.sf.json.JSONObject;
import org.springframework.core.io.InputStreamResource;
import org.springframework.core.io.Resource;
import org.springframework.http.ContentDisposition;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;

@Slf4j
@Service
public class FileService {
    private final String logDir= "/logs/";
    private final String sysDir= System.getProperty("user.dir");
    private final String[] exceptDir ={"backup"};
    private int id = 1;

    public String getView(HttpServletRequest request, String fileName, String filePath) {
        long preEndPoint = request.getParameter("preEndPoint") == null ? 0 : Long.parseLong(request.getParameter("preEndPoint") + "");
        StringBuilder sb = new StringBuilder();
        long startPoint, endPoint;
        RandomAccessFile file = null;
        String errMsg = "";

        try {
            file = new RandomAccessFile(System.getProperty("user.dir") + filePath + fileName, "r");
            endPoint = file.length();
            startPoint = preEndPoint > 0 ? preEndPoint : endPoint < 2000 ? 0 : endPoint - 2000;
            file.seek(startPoint);

            String str;
            while ((str = file.readLine()) != null) {
                byte[] b = str.getBytes("iso-8859-1");
                str = new String(b, "UTF-8");
                sb.append(str);
                sb.append("<br>");
                endPoint = file.getFilePointer();
                file.seek(endPoint);
            }

            JSONObject json = new JSONObject();
            json.put("endPoint", endPoint);
            json.put("log", sb.toString());
            return json.toString();
        }
        catch(FileNotFoundException fnf) {
            log.error("FileService.getView: Exception: {}", fnf.toString());
            errMsg += fnf.toString();
        }
        catch (IOException e) {
            log.error(e.getMessage());
            errMsg += e.toString();
        }
        finally {
            try {
                if (file != null) file.close();
            }
            catch (Exception e) {
                log.error("FileService.getView: Exception: {}", e.toString());
                errMsg += e.toString();
            }
        }

        if (!errMsg.equals("")) {
            sb.append(errMsg);
            sb.append("<br>");
            JSONObject json = new JSONObject();
            json.put("endPoint", 0);
            json.put("log", sb.toString());
            return json.toString();
        }
        return null;
    }

    public ResponseEntity<Resource> fileDownload(String fileName, String filePath){
        try {
            Path path = Paths.get(System.getProperty("user.dir")+filePath+ fileName);
            String contentType = "application/download";
            HttpHeaders headers = new HttpHeaders();
            headers.add(HttpHeaders.CONTENT_TYPE, contentType);
            headers.setContentDisposition(ContentDisposition.parse("attachment;" + " filename=\"" + fileName + "\";"));
            Resource resource = new InputStreamResource(Files.newInputStream(path));

            return new ResponseEntity<>(resource, headers, HttpStatus.OK);
        }
        catch (IOException e) {
            log.error("FileService.fileDownload: Exception: {}", e.toString());
        }
        return null;
    }

    public void fileDelete(String fileName,String filePath) {
        File file = new File(this.sysDir+filePath+fileName);
        if (file.exists()) {
            if (file.delete()) {
                log.info("FileService.fileDelete: Delete Success: {}", filePath+fileName);
            }
            else {
                log.error("FileService.fileDelete: Delete Fail: {}", filePath+fileName);
            }
        }
        else {
            log.warn("FileService.fileDelete: Not exists: {}", filePath+fileName);
        }
    }

    public List<FileInfoVo> getLogFiles() {
        this.id = 1;
        FileInfoVo rootFile = new FileInfoVo();
        rootFile.setId(id);
        rootFile.setType("dir");
        this.id++;
        rootFile.setFileName("logs");
        rootFile.setFileInfos(getFiles(this.sysDir, this.logDir));
        List<FileInfoVo> fileInfos = new ArrayList<>();
        fileInfos.add(rootFile);
        return fileInfos;
    }

    private List<FileInfoVo> getFiles(String sysDir, String logDir) {
        int rootId = id - 1;
        //log.debug("FileService.getFiles: id: {}, sysDir: {}, logDir: {}", id, sysDir, logDir);
        List<FileInfoVo> subArr = new ArrayList<>();
        File dirFile = new File(sysDir, logDir);
        File[] fileList = dirFile.listFiles();

        for (File file: fileList) {
            FileInfoVo info = new FileInfoVo();
            //log.debug("FileService.getFiles: getName: {}, isDir: {}, getPath: {}", file.getName(), file.isDirectory(), file.getPath());

            if (file.isDirectory()) {
                for (String dir : exceptDir) {
                    if (dir.equals(file.getName())) {
                        break;
                    }
                    else {
                        String subDir = file.getPath().substring(file.getPath().indexOf(logDir.replaceAll("/", "")), file.getPath().length());
                        info.setId(id);
                        id++;
                        String sFileSeparator = "/";
                        info.setFilePath(sFileSeparator + subDir);
                        info.setFileName(file.getName());
                        info.setFileSize(file.length());
                        info.setType("dir");

                        info.setFileInfos(getFiles(sysDir,  subDir));
                        info.setParentId(rootId);
                        //log.info(info.toString());
                        subArr.add(info);
                    }
                }
            }
        }

        //log.debug("x: {}", fileList.toString());
        for (File file: fileList) {
            FileInfoVo info = new FileInfoVo();
            if (file.isFile() && file.getName().contains(".log")) {
                info.setId(id);
                id++;
                info.setFileName(file.getName());
                info.setFileSize(file.length());
                String subDir;
                if (OS.isWindows()) {
                    subDir = file.getPath().substring(file.getPath().indexOf(logDir.replaceAll("/","")), file.getPath().length() - file.getName().length()).replaceAll("\\\\", "/");
                } else {
                    subDir = file.getPath().substring(file.getPath().indexOf(logDir), file.getPath().length() - file.getName().length()).replaceAll("\\\\", "/");
                }

                String sFileSeparator = "/";
                info.setFilePath(sFileSeparator + subDir);
                info.setType("log");
                info.setParentId(rootId);
                //log.info(info.toString());
                subArr.add(info);
            }
        }
        //log.debug("y: {}", subArr.toString());
        return subArr;
    }

}
