package cn.com.yict.framemax.log4j;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.apache.commons.lang3.time.FastDateFormat;
import org.apache.log4j.helpers.LogLog;

import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.attribute.PosixFilePermission;
import java.text.ParseException;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;

/**
 * @author Focan Zhong
 * @create 2021/10/9
 */
public class MyDailyRollingFileAppender extends org.apache.log4j.DailyRollingFileAppender {

    /**
     * There is one backup file by default.
     */
    protected int maxBackupIndex = -1;
    protected String backupDir;

    protected void doBackupfile() {
        if (this.maxBackupIndex > 0) {
            try {
                File[] files = getBackupFiles();
                if (files != null && files.length > 0) {
                    for (File file : files) {
                        file.delete();
                    }
                }
            } catch (Exception ex) {
                LogLog.error("Delete backup file failed.", ex);
            }
        }
    }

    @Override
    protected void closeFile() {
        this.doBackupfile();
        super.closeFile();
    }

    protected File[] getBackupFiles() throws ParseException {
        final File file = new File(super.fileName);
        final String logFileName = file.getName();
        final FastDateFormat dateFormat = FastDateFormat.getInstance(getDatePattern());
        final Date day = dateFormat.parse(dateFormat.format(DateUtils.addDays(new Date(), -maxBackupIndex)));
        final int index = logFileName.length();
        FilenameFilter filter = new FilenameFilter() {
            @Override
            public boolean accept(File dir, String name) {
                return !logFileName.equals(name) &&
                        name.length() > index &&
                        name.startsWith(logFileName) &&
                        lt(name.substring(index), day, dateFormat);
            }
        };

        String perentDirectory = file.getParent();
        if (file.exists()) {
            if (file.getParent() == null) {
                String absolutePath = file.getAbsolutePath();
                perentDirectory = absolutePath.substring(0, absolutePath.lastIndexOf(fileName));

            }
        }
        File dir = StringUtils.isEmpty(backupDir) ? new File(perentDirectory) : new File(perentDirectory, backupDir);
        return dir.listFiles(filter);
    }

    private static boolean lt(String src, Date limitDate, FastDateFormat dateFormat) {
        try {
            Date date = dateFormat.parse(src);
            return date.compareTo(limitDate) < 0;
        } catch (Exception ex) {
            //ignore
        }
        return false;
    }

    public int getMaxBackupIndex() {
        return maxBackupIndex;
    }

    public void setMaxBackupIndex(int maxBackupIndex) {
        this.maxBackupIndex = maxBackupIndex;
    }

    public String getBackupDir() {
        return backupDir;
    }

    public void setBackupDir(String backupDir) {
        this.backupDir = backupDir;
    }

    /**
     * 日志文件权限
     * 权限 755
     *
     * @param fileName
     * @param append
     * @param bufferedIO
     * @param bufferSize
     * @throws IOException
     */
    @Override
    public synchronized void setFile(String fileName, boolean append, boolean bufferedIO, int bufferSize) throws IOException {
        super.setFile(fileName, append, bufferedIO, bufferSize);
        File f = new File(fileName);
        Set<PosixFilePermission> set = new HashSet<>();
        //设置所有者权限
        set.add(PosixFilePermission.OWNER_READ);
        set.add(PosixFilePermission.OWNER_WRITE);
        set.add(PosixFilePermission.OWNER_EXECUTE);
        //设置同组用户权限
        set.add(PosixFilePermission.GROUP_READ);
        set.add(PosixFilePermission.GROUP_EXECUTE);
        //设置其他用户权限
        set.add(PosixFilePermission.OTHERS_READ);
        set.add(PosixFilePermission.OTHERS_EXECUTE);
        if (f.exists()) {
            Files.setPosixFilePermissions(f.toPath(), set);
        }
    }
}
