package com.bmc.arsys.demo.javadriver;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Stack;

/**
 * ThreadLocal methods related to Performance test
 * @author Yucheng Huang
 * May 29, 2007
 */
public class PerfThreadControlBlock extends ThreadControlBlock {
    long auxCount;

    private int resultFileCount;

    private String resultFileName;

    PrintWriter resultFile;

    Stack<String> resultStack;

    /* (non-Javadoc)
     * @see com.bmc.arsys.demo.javadriver.ThreadControlBlock#isResultFileOpened()
     */
    @Override
    public boolean isResultFileOpened() {
        if ((PerfJavaDriver.getOutputSetting() & PerfJavaDriver.OUT_MODE_PERF_LOG_MEM) != 0) {
            if (resultStack == null) {
                return false;
            } else {
                return true;
            }
        } else {
            if (resultFile == null) {
                return false;
            } else {
                return true;
            }
        }
    }

    /* (non-Javadoc)
     * @see com.bmc.arsys.demo.javadriver.ThreadControlBlock#writeInResultFile(java.lang.String)
     */
    @Override
    public void writeInResultFile(String content) {
        if ((PerfJavaDriver.getOutputSetting() & PerfJavaDriver.OUT_MODE_PERF_LOG_MEM) != 0) {
            if (resultStack == null) {
                resultStack = new Stack<String>();
            }
            resultStack.push(content);
        } else if (PerfJavaDriver.isForOutputFile()) {
            resultFile.println(content);
        }
    }

    /* (non-Javadoc)
     * @see com.bmc.arsys.demo.javadriver.ThreadControlBlock#logTransaction(java.lang.String)
     */
    @Override
    protected void logTransaction(String commentLine) throws IOException {
        super.logTransaction(commentLine);
        // process if we are doing some form of performance logging
        if (!JavaDriver.javaDriverOnly
                && (PerfJavaDriver.getOutputSetting() & (PerfJavaDriver.OUT_MODE_PERF_LOG | PerfJavaDriver.OUT_MODE_PERF_LOG_MEM)) != 0) {
            // process if this is the first logging we've done for the current thread
            if (getResultFile() == null) {
                initLogMethod();
            }
            writeInResultFile(commentLine);
            if (commentLine.startsWith("## transaction end") && resultFile!= null) {
                resultFile.flush();
            }
        }
    }

    public void initLogMethod() throws IOException {
        if ((PerfJavaDriver.getOutputSetting() & PerfJavaDriver.OUT_MODE_PERF_LOG_MEM) != 0) {
            setResultStack();
        } else {
            // increment the count for the number of files created so we
            // can have a unique number available for file name creation
            String fullFileName = preparePerfResultFileName();

            setResultFile(fullFileName);

            // write a comment into the file that allows this file to be
            // cross-referenced with its corresponding output file
            if (getOutputFileName() != null) {
                writeInResultFile("\n" + "Corresponding Output File: " + getOutputFileName() + "\n");
            }
        }
    }

    protected String preparePerfResultFileName() {
        // increment the count for the number of files created so we
        // can have a unique number available for file name creation
        resultFileCount = PerfJavaDriver.getAndIncrementTheFileCount();
        String fileCountStr = String.valueOf(resultFileCount);
        StringBuilder prefix = new StringBuilder();
        for (int i = fileCountStr.length(); i < 5; i++) {
            prefix.append("0");
        }
        StringBuilder fileName = new StringBuilder();
        fileName.append("perf_").append(prefix.toString()).append(fileCountStr).append(".log");
        String fullFileName = fileName.toString();

        if (JavaDriver.getResultDirectory() != null) {
            fullFileName = JavaDriver.getResultDirectory() + "\\" + fullFileName;
        }
        return fullFileName;
    }

    public long getAuxCount() {
        return auxCount;
    }

    public void setAuxCount(long count) {
        auxCount = count;
    }

    public Stack<String> getResultStack() {
        return resultStack;
    }

    public PrintWriter getResultFile() {
        return resultFile;
    }

    public void closeResultFile() {
        if (resultFile != null) {
            resultFile.flush();
            resultFile.close();
            resultFile = null;
        }
    }

    public void closeResultStack() {
        if (resultStack != null && !resultStack.empty()) {
            resultStack.clear();
        }
    }

    public void setResultStack() {
        resultStack = new Stack<String>();
    }

    public void setResultFile(String fileName) throws IOException {
        resultFileName = fileName;
        resultFile = new PrintWriter(new FileOutputStream(new File(fileName)));
    }

    public boolean hasResultFile() {
        return (resultFileName == null) ? false : true;
    }

    public void setResultFileCount(int count) {
        resultFileCount = count;
    }

    /**
     * @return the outputCount
     */
    public int getResultFileCount() {
        return resultFileCount;
    }

    @Override
    protected void threadSleep(long sleepTimeInMilliSeconds) {
        long sleepTime = sleepTimeInMilliSeconds / CommandProcessor.SLEEP_ADJUST_FACTOR;
        long elapsedTimeMilliSec = System.currentTimeMillis() - PerfJavaDriver.driverStartTime;

        //  process depending if the intention is to log the results to memory
        //  or directly to a file

        String statString = PerfJavaDriver.getStatString(elapsedTimeMilliSec, getCurrentCommand(), 0, sleepTime);
        writeInResultFile(statString);
        if (resultFile!= null)
            resultFile.flush();
        super.threadSleep(sleepTime);
    }

}
