/* ====================================================================
   Licensed to the Apache Software Foundation (ASF) under one or more
   contributor license agreements.  See the NOTICE file distributed with
   this work for additional information regarding copyright ownership.
   The ASF licenses this file to You under the Apache License, Version 2.0
   (the "License"); you may not use this file except in compliance with
   the License.  You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
==================================================================== */
package org.apache.poi;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;

/**
 * Centralises logic for finding/opening sample files
 */
public final class POIDataSamples {

    /**
     * Name of the system property that defined path to the test data.
     */
    public static final String TEST_PROPERTY = "POI.testdata.path";

    private static POIDataSamples _instSlideshow;
    private static POIDataSamples _instSpreadsheet;
    private static POIDataSamples _instDocument;
    private static POIDataSamples _instDiagram;
    private static POIDataSamples _instOpenxml4j;
    private static POIDataSamples _instPOIFS;
    private static POIDataSamples _instDDF;
    private static POIDataSamples _instHMEF;
    private static POIDataSamples _instHPSF;
    private static POIDataSamples _instHPBF;
    private static POIDataSamples _instHSMF;
    private static POIDataSamples _instXmlDSign;

    private File _resolvedDataDir;
    /** <code>true</code> if standard system propery is not set,
     * but the data is available on the test runtime classpath */
    private boolean _sampleDataIsAvaliableOnClassPath;
    private final String _moduleDir;

    /**
     *
     * @param moduleDir   the name of the directory containing the test files
     */
    private POIDataSamples(String moduleDir){
        _moduleDir = moduleDir;
        initialise();
    }

    public static POIDataSamples getSpreadSheetInstance(){
        if(_instSpreadsheet == null) _instSpreadsheet = new POIDataSamples("spreadsheet");
        return _instSpreadsheet;
    }

    public static POIDataSamples getDocumentInstance(){
        if(_instDocument == null) _instDocument = new POIDataSamples("document");
        return _instDocument;
    }

    public static POIDataSamples getSlideShowInstance(){
        if(_instSlideshow == null) _instSlideshow = new POIDataSamples("slideshow");
        return _instSlideshow;
    }

    public static POIDataSamples getDiagramInstance(){
        if(_instOpenxml4j == null) _instOpenxml4j = new POIDataSamples("diagram");
        return _instOpenxml4j;
    }

    public static POIDataSamples getOpenXML4JInstance(){
        if(_instDiagram == null) _instDiagram = new POIDataSamples("openxml4j");
        return _instDiagram;
    }

    public static POIDataSamples getPOIFSInstance(){
        if(_instPOIFS == null) _instPOIFS = new POIDataSamples("poifs");
        return _instPOIFS;
    }

    public static POIDataSamples getDDFInstance(){
        if(_instDDF == null) _instDDF = new POIDataSamples("ddf");
        return _instDDF;
    }

    public static POIDataSamples getHPSFInstance(){
        if(_instHPSF == null) _instHPSF = new POIDataSamples("hpsf");
        return _instHPSF;
    }

    public static POIDataSamples getPublisherInstance(){
        if(_instHPBF == null) _instHPBF = new POIDataSamples("publisher");
        return _instHPBF;
    }

    public static POIDataSamples getHMEFInstance(){
        if(_instHMEF == null) _instHMEF = new POIDataSamples("hmef");
        return _instHMEF;
    }

    public static POIDataSamples getHSMFInstance(){
        if(_instHSMF == null) _instHSMF = new POIDataSamples("hsmf");
        return _instHSMF;
    }

    public static POIDataSamples getXmlDSignInstance() {
        if(_instXmlDSign == null) _instXmlDSign = new POIDataSamples("xmldsign");
        return _instXmlDSign;
    }

    /**
     * Opens a sample file from the test data directory
     *
     * @param  sampleFileName the file to open
     * @return an open <tt>InputStream</tt> for the specified sample file
     */
    public InputStream openResourceAsStream(String sampleFileName) {

        if (_sampleDataIsAvaliableOnClassPath) {
            InputStream result = sampleFileName == null ? null :
                    openClasspathResource(sampleFileName);
            if(result == null) {
                throw new RuntimeException("specified test sample file '" + sampleFileName
                        + "' not found on the classpath");
            }
            // wrap to avoid temp warning method about auto-closing input stream
            return new NonSeekableInputStream(result);
        }
        if (_resolvedDataDir == null) {
            throw new RuntimeException("Must set system property '"
                    + TEST_PROPERTY
                    + "' properly before running tests");
        }

        File f = getFile(sampleFileName);
        try {
            return new FileInputStream(f);
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     *
     * @param sampleFileName    the name of the test file
     * @return Verifies that the file with the given name exists in the test-data directory
     * @throws RuntimeException if the file was not found
     */
    public File getFile(String sampleFileName) {
        File f = new File(_resolvedDataDir, sampleFileName);
        if (!f.exists()) {
            throw new RuntimeException("Sample file '" + sampleFileName
                    + "' not found in data dir '" + _resolvedDataDir.getAbsolutePath() + "'");
        }
        try {
            if(sampleFileName.length() > 0) {
               String fn = sampleFileName;
               if(fn.indexOf('/') > 0) {
                  fn = fn.substring(fn.indexOf('/')+1);
               }
               if(!fn.equals(f.getCanonicalFile().getName())){
                   throw new RuntimeException("File name is case-sensitive: requested '" + fn
                        + "' but actual file is '" + f.getCanonicalFile().getName() + "'");
               }
            }
        } catch (IOException e){
            throw new RuntimeException(e);
        }
        return f;
    }

    private void initialise() {
        String dataDirName = System.getProperty(TEST_PROPERTY);
        if (dataDirName == null) {
            // check to see if we can just get the resources from the classpath
            InputStream is = openClasspathResource("");
            if (is != null) {
                try {
                    is.close(); // be nice
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
                _sampleDataIsAvaliableOnClassPath = true;
                return;
            }

            if (new File("test-data").exists()) {
				dataDirName = "test-data";
			} else if (new File("../test-data").exists()) {
               dataDirName = "../test-data";
            } else {
               throw new RuntimeException("Must set system property '" +
                       TEST_PROPERTY + "' before running tests");
            }
        }
        File dataDir = new File(dataDirName, _moduleDir);
        if (!dataDir.exists()) {
            throw new RuntimeException("Data dir '" + dataDir + "' does not exist");
        }
        // convert to canonical file, to make any subsequent error messages
        // clearer.
        try {
            _resolvedDataDir = dataDir.getCanonicalFile();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * Opens a test sample file from the 'data' sub-package of this class's package.
     *
     * @param  sampleFileName the file to open
     * @return <code>null</code> if the sample file is not deployed on the classpath.
     */
    private InputStream openClasspathResource(String sampleFileName) {
        return getClass().getResourceAsStream("/" + _moduleDir + "/" + sampleFileName);
    }

    private static final class NonSeekableInputStream extends InputStream {

        private final InputStream _is;

        public NonSeekableInputStream(InputStream is) {
            _is = is;
        }

        @Override
        public int read() throws IOException {
            return _is.read();
        }
        @Override
        public int read(byte[] b, int off, int len) throws IOException {
            return _is.read(b, off, len);
        }
        @Override
        public boolean markSupported() {
            return false;
        }
        @Override
        public void close() throws IOException {
            _is.close();
        }
    }

    /**
     * @param  fileName the file to open
     * @return byte array of sample file content from file found in standard test-data directory
     */
    public byte[] readFile(String fileName) {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();

        try {
            InputStream fis = openResourceAsStream(fileName);

            byte[] buf = new byte[512];
            while (true) {
                int bytesRead = fis.read(buf);
                if (bytesRead < 1) {
                    break;
                }
                bos.write(buf, 0, bytesRead);
            }
            fis.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return bos.toByteArray();
    }

}
