/* ====================================================================
   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.poifs.filesystem;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Random;

import org.apache.poi.POIDataSamples;
import org.apache.poi.util.TempFile;
import org.junit.Test;

public class TestFileMagic {
    @Test
    public void testFileMagic() {
        assertEquals(FileMagic.XML, FileMagic.valueOf("XML"));
        assertEquals(FileMagic.XML, FileMagic.valueOf("<?xml".getBytes(StandardCharsets.UTF_8)));

        assertEquals(FileMagic.HTML, FileMagic.valueOf("HTML"));
        assertEquals(FileMagic.HTML, FileMagic.valueOf("<!DOCTYP".getBytes(StandardCharsets.UTF_8)));
        assertEquals(FileMagic.HTML, FileMagic.valueOf("<!DOCTYPE".getBytes(StandardCharsets.UTF_8)));
        assertEquals(FileMagic.HTML, FileMagic.valueOf("<html".getBytes(StandardCharsets.UTF_8)));
        assertEquals(FileMagic.HTML, FileMagic.valueOf("\n\r<html".getBytes(StandardCharsets.UTF_8)));
        assertEquals(FileMagic.HTML, FileMagic.valueOf("\n<html".getBytes(StandardCharsets.UTF_8)));
        assertEquals(FileMagic.HTML, FileMagic.valueOf("\r\n<html".getBytes(StandardCharsets.UTF_8)));
        assertEquals(FileMagic.HTML, FileMagic.valueOf("\r<html".getBytes(StandardCharsets.UTF_8)));

        assertEquals(FileMagic.JPEG, FileMagic.valueOf(new byte[]{ (byte)0xFF, (byte)0xD8, (byte)0xFF, (byte)0xDB }));
        assertEquals(FileMagic.JPEG, FileMagic.valueOf(new byte[]{ (byte)0xFF, (byte)0xD8, (byte)0xFF, (byte)0xE0, 'a', 'b', 'J', 'F', 'I', 'F', 0x00, 0x01 }));
        assertEquals(FileMagic.JPEG, FileMagic.valueOf(new byte[]{ (byte)0xFF, (byte)0xD8, (byte)0xFF, (byte)0xEE }));
        assertEquals(FileMagic.JPEG, FileMagic.valueOf(new byte[]{ (byte)0xFF, (byte)0xD8, (byte)0xFF, (byte)0xE1, 'd', 'c', 'E', 'x', 'i', 'f', 0x00, 0x00 }));

        assertEquals(FileMagic.UNKNOWN, FileMagic.valueOf("something".getBytes(StandardCharsets.UTF_8)));
        assertEquals(FileMagic.UNKNOWN, FileMagic.valueOf(new byte[0]));

        try {
            FileMagic.valueOf("some string");
            fail("Should catch exception here");
        } catch (IllegalArgumentException e) {
            // expected here
        }
    }

    @Test
    public void testFileMagicFile() throws IOException {
        assertEquals(FileMagic.OLE2, FileMagic.valueOf(POIDataSamples.getSpreadSheetInstance().getFile("SampleSS.xls")));
        assertEquals(FileMagic.OOXML, FileMagic.valueOf(POIDataSamples.getSpreadSheetInstance().getFile("SampleSS.xlsx")));
    }

    @Test
    public void testFileMagicStream() throws IOException {
        try (InputStream stream = new BufferedInputStream(new FileInputStream(POIDataSamples.getSpreadSheetInstance().getFile("SampleSS.xls")))) {
            assertEquals(FileMagic.OLE2, FileMagic.valueOf(stream));
        }
        try (InputStream stream = new BufferedInputStream(new FileInputStream(POIDataSamples.getSpreadSheetInstance().getFile("SampleSS.xlsx")))) {
            assertEquals(FileMagic.OOXML, FileMagic.valueOf(stream));
        }
    }

    @Test
    public void testPrepare() throws IOException {
        try (InputStream stream = new BufferedInputStream(new FileInputStream(POIDataSamples.getSpreadSheetInstance().getFile("SampleSS.xlsx")))) {
            assertSame(stream, FileMagic.prepareToCheckMagic(stream));
        }

        try (InputStream stream = new InputStream() {
            @Override
            public int read() {
                return 0;
            }
        }) {
            assertNotSame(stream, FileMagic.prepareToCheckMagic(stream));
        }
    }

    @Test
    public void testMatchingButTooLessData() {
        // this matches JPG, but is not long enough, previously this caused an Exception
        byte[] data = new byte[] { -1, -40, -1, -32, 0, 16, 74, 70 };

        assertEquals(FileMagic.UNKNOWN, FileMagic.valueOf(data));
    }

    @Test
    public void testShortFile() throws IOException {
        // having a file shorter than 8 bytes previously caused an exception
        fetchMagicFromData(new byte[] { -1, -40, -1, -32, 0 });
        fetchMagicFromData(new byte[] { -1, -40, -1, -32 });
        fetchMagicFromData(new byte[] { -1, -40, -1 });
        fetchMagicFromData(new byte[] { -1, -40 });
        fetchMagicFromData(new byte[] { -1 });
        fetchMagicFromData(new byte[0]);
    }

    private void fetchMagicFromData(byte[] data) throws IOException {
        File file = TempFile.createTempFile("TestFileMagic", ".bin");
        try {
            try (FileOutputStream fos = new FileOutputStream(file)) {
                fos.write(data);
            }

            assertEquals(FileMagic.UNKNOWN, FileMagic.valueOf(file));
        } finally {
            assertTrue(file.delete());
        }
    }

    @Test(expected = IOException.class)
    public void testMarkRequired() throws IOException {
        byte[] data = new byte[] { -1, -40, -1, -32, 0 };

        File file = TempFile.createTempFile("TestFileMagic", ".bin");
        try {
            try (FileOutputStream fos = new FileOutputStream(file)) {
                fos.write(data);
            }

            // a FileInputStream does not support "marking"
            try (FileInputStream str = new FileInputStream(file)) {
                assertFalse(str.markSupported());

                FileMagic.valueOf(str);
            }
        } finally {
            assertTrue(file.delete());
        }
    }

    @Test
    public void testPatterns() {
        // just try to trash the functionality with some byte-patterns
        for(int i = 0; i < 256;i++) {
            final byte[] data = new byte[12];
            for(int j = 0;j < 12; j++) {
                data[j] = (byte)i;

                assertEquals(FileMagic.UNKNOWN, FileMagic.valueOf(data));
            }
        }
    }

    @Test
    public void testRandomPatterns() {
        Random random = new Random();

        // just try to trash the functionality with some byte-patterns
        for(int i = 0; i < 1000;i++) {
            final byte[] data = new byte[12];
            random.nextBytes(data);

            // we cannot check for UNKNOWN as we might hit valid byte-patterns here as well
            try {
                assertNotNull(FileMagic.valueOf(data));
            } catch (Exception e) {
                throw new IllegalStateException("Failed with pattern " + Arrays.toString(data), e);
            }
        }
    }
}
