package jp.hrtdotnet.java.io;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;

import jp.hrtdotnet.java.HTestCase;

public class HFileTest extends HTestCase {


    private HFile file;
    private String path;
    private String tmp = System.getProperty("java.io.tmpdir") + "hdntest" + File.separator;
    
    protected void setUp() throws Exception {
        super.setUp();
        init();
    }
    
    private void init() throws IOException {
        File f = new File(tmp);
        if (f.exists() && f.isFile()) {            
            throw new RuntimeException();
        }
        if (!f.exists()) {
            f.mkdirs();
        }
        Calendar c = Calendar.getInstance();
        DateFormat df = new SimpleDateFormat("yyyyMMddHHmmssSSS");
        path = tmp + df.format(c.getTime());
        file = new HFile(path + ".dat");
        file.createNewFile();
    }
    
    protected void tearDown() throws Exception {
        super.tearDown();
        dispose();
    }

    private void dispose() {
        file.delete();
        File f = new File(tmp);
        f.delete();
    }
    
    private void next() throws IOException {
        dispose();
        init();
    }
    
    /**
     * {@link jp.hrtdotnet.java.io.HFile#mkdir()} のためのテスト・メソッド。
     */
    public void testMkdir() {
        //不要
    }

    /**
     * {@link jp.hrtdotnet.java.io.HFile#mkdirs()} のためのテスト・メソッド。
     */
    public void testMkdirs() {
        //不要
    }

    /**
     * {@link jp.hrtdotnet.java.io.HFile#HFile(java.lang.String)} のためのテスト・メソッド。
     * @throws IOException 
     */
    public void testHFile_String() throws IOException {
        new HFile(testClassResources.getString("file"));
        
        try {
            new HFile("....");
            fail();
        } catch (IOException e) {
        }

        try {
            new HFile(testClassResources.getString("directory"));
            fail();
        } catch (IOException e) {
        }
    }

    /**
     * {@link jp.hrtdotnet.java.io.HFile#HFile(java.lang.String, java.lang.String)} のためのテスト・メソッド。
     * @throws IOException 
     */
    public void testHFile_StringString() throws IOException {
        new HFile(testClassResources.getString("fileParent"), testClassResources.getString("fileChild"));
        
        try {
            new HFile("....");
            fail();
        } catch (IOException e) {
        }

        try {
            new HFile(testClassResources.getString("directoryParent"), testClassResources.getString("directoryChild"));
            fail();
        } catch (IOException e) {
        }

    }

    /**
     * {@link jp.hrtdotnet.java.io.HFile#getExtension()} のためのテスト・メソッド。
     * @throws IOException 
     */
    public void testGetExtension() throws IOException {
        assertEquals(file.getExtension(), "dat");
        file = new HFile("test");
        assertEquals(file.getExtension(), "");
    }

    /**
     * {@link jp.hrtdotnet.java.io.HFile#getOtherFileName(java.lang.String, int)} のためのテスト・メソッド。
     * @throws IOException 
     */
    public void testGetOtherFileName_StringInt() throws IOException {
        HFile file = new HFile(tmp + "test.dat");
        file.createNewFile();
        assertEquals(file.getOtherFileName("+", 3), tmp + "test+000.dat");
        HFile file2 = new HFile(file.getOtherFileName("+", 3));
        file2.createNewFile();
        assertEquals(file.getOtherFileName("+", 3), tmp + "test+001.dat");
        file.delete();
        file2.delete();
    }

    /**
     * {@link jp.hrtdotnet.java.io.HFile#getOtherFileName(java.lang.String)} のためのテスト・メソッド。
     * @throws IOException 
     */
    public void testGetOtherFileName_String() throws IOException {
        HFile file = new HFile(tmp + "test.dat");
        file.createNewFile();
        assertEquals(file.getOtherFileName("~"), tmp + "test~1.dat");
        HFile file2 = new HFile(file.getOtherFileName("~"));
        file2.createNewFile();
        assertEquals(file.getOtherFileName("~"), tmp + "test~2.dat");
        file.delete();
        file2.delete();
    }

    /**
     * {@link jp.hrtdotnet.java.io.HFile#checkFileName(java.lang.String)} のためのテスト・メソッド。
     */
    public void testCheckFileName() {
        
        //<li>null</li>
        assertFalse(HFile.checkFileName(null));

        //<li>長さが0バイト（空文字）、256バイト以上</li>
        assertFalse(HFile.checkFileName(""));

        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < 255; i++) {
            sb.append("a");
        }
        assertTrue(HFile.checkFileName(sb.toString()));
        sb.append("a");
        assertFalse(HFile.checkFileName(sb.toString()));

        sb = new StringBuffer();
        for (int i = 0; i < 127; i++) {
            sb.append("あ");
        }
        sb.append("a");
        assertTrue(HFile.checkFileName(sb.toString()));
        sb.append("a");
        assertFalse(HFile.checkFileName(sb.toString()));

        //<li>大小区別せずに頭文字が「CON.」「AUX.」「PRN.」「NUL.」から始まる</li>
        assertFalse(HFile.checkFileName("CON."));
        assertFalse(HFile.checkFileName("AUX."));
        assertFalse(HFile.checkFileName("PRN."));
        assertFalse(HFile.checkFileName("NUL."));
        assertFalse(HFile.checkFileName("cON."));
        assertFalse(HFile.checkFileName("AuX."));
        assertFalse(HFile.checkFileName("PRn."));
        assertFalse(HFile.checkFileName("nUL."));
        assertFalse(HFile.checkFileName("con."));
        assertFalse(HFile.checkFileName("aux."));
        assertFalse(HFile.checkFileName("prn."));
        assertFalse(HFile.checkFileName("nul."));

        assertFalse(HFile.checkFileName("CON.a"));
        assertFalse(HFile.checkFileName("AUX.a"));
        assertFalse(HFile.checkFileName("PRN.a"));
        assertFalse(HFile.checkFileName("NUL.a"));
        assertFalse(HFile.checkFileName("cON.a"));
        assertFalse(HFile.checkFileName("AuX.a"));
        assertFalse(HFile.checkFileName("PRn.a"));
        assertFalse(HFile.checkFileName("nUL.a"));
        assertFalse(HFile.checkFileName("con.a"));
        assertFalse(HFile.checkFileName("aux.a"));
        assertFalse(HFile.checkFileName("prn.a"));
        assertFalse(HFile.checkFileName("nul.a"));

        assertTrue(HFile.checkFileName("aCON.a"));
        assertTrue(HFile.checkFileName("aAUX.a"));
        assertTrue(HFile.checkFileName("aPRN.a"));
        assertTrue(HFile.checkFileName("aNUL.a"));
        assertTrue(HFile.checkFileName("acON.a"));
        assertTrue(HFile.checkFileName("aAuX.a"));
        assertTrue(HFile.checkFileName("aPRn.a"));
        assertTrue(HFile.checkFileName("anUL.a"));
        assertTrue(HFile.checkFileName("acon.a"));
        assertTrue(HFile.checkFileName("aaux.a"));
        assertTrue(HFile.checkFileName("aprn.a"));
        assertTrue(HFile.checkFileName("anul.a"));

        //<li>拡張子を除いた名前が「COM[0-9]」「LPT[0-9]」のもの（[0-9]は0〜9のどれか）</li>
        for (int i = 0; i < 10; i++) {
            assertFalse(HFile.checkFileName("COM" + i));
            assertFalse(HFile.checkFileName("LPT" + i));
            assertFalse(HFile.checkFileName("COM" + i + ".txt"));
            assertFalse(HFile.checkFileName("LPT" + i + ".txt"));
            assertTrue(HFile.checkFileName("COM" + i + "a"));
            assertTrue(HFile.checkFileName("LPT" + i + "a"));
            assertTrue(HFile.checkFileName("aCOM" + i));
            assertTrue(HFile.checkFileName("aLPT" + i));
        }
        assertTrue(HFile.checkFileName("COMa"));
        assertTrue(HFile.checkFileName("LPTa"));

        //<li>「/」「\」「:」「*」「?」「&quot;」「&lt;」「&gt;」「|」を含む</li>
        assertFalse(HFile.checkFileName("a/a"));
        assertFalse(HFile.checkFileName("a\\a"));
        assertFalse(HFile.checkFileName("a:a"));
        assertFalse(HFile.checkFileName("a*a"));
        assertFalse(HFile.checkFileName("a\"a"));
        assertFalse(HFile.checkFileName("a<a"));
        assertFalse(HFile.checkFileName("a>a"));
        assertFalse(HFile.checkFileName("a|a"));
        assertTrue(HFile.checkFileName("a'a"));

        //<li>末尾が「.」（ドット）</li>
        assertFalse(HFile.checkFileName("aaa/"));
        
    }

    /**
     * {@link jp.hrtdotnet.java.io.HFile#renameExtension(java.lang.String)} のためのテスト・メソッド。
     * @throws IOException 
     */
    public void testRenameExtension() throws IOException {
        assertTrue(file.renameExtension("txt"));
        File f = new File(path + ".txt");
        assertTrue(f.isFile());
        f.delete();

        next();

        assertTrue(file.renameExtension(""));
        f = new File(path);
        assertTrue(f.isFile());
        f.delete();
        
        next();

        try {
            file.renameExtension(null);
            fail();
        } catch (IllegalArgumentException e) {            
        }
        
        next();

        try {
            file.renameExtension(".");
            fail();
        } catch (IllegalArgumentException e) {            
        }
    }

    /**
     * {@link jp.hrtdotnet.java.io.HFile#copy(java.io.OutputStream)} のためのテスト・メソッド。
     * @throws IOException 
     */
    public void testCopy_OutputStream() throws IOException {
        HFile f = new HFile(testClassResources.getString("file"));
        Calendar c = Calendar.getInstance();
        DateFormat df = new SimpleDateFormat("yyyyMMddHHmmssSSS");
        File f2 = new File(tmp + df.format(c.getTime()));
        if (f2.exists()) {
            throw new RuntimeException(tmp + " is exists.");
        }
        FileOutputStream out = new FileOutputStream(f2);
        f.copy(out);
        out.close();
        if (f2.exists()) {
            f2.delete();            
        } else {
            fail();
        }
    }

    /**
     * {@link jp.hrtdotnet.java.io.HFile#copy(java.io.File)} のためのテスト・メソッド。
     * @throws IOException 
     */
    public void testCopy_File() throws IOException {
        HFile f = new HFile(testClassResources.getString("file"));
        Calendar c = Calendar.getInstance();
        DateFormat df = new SimpleDateFormat("yyyyMMddHHmmssSSS");
        File f2 = new File(tmp + df.format(c.getTime()));
        if (f2.exists()) {
            throw new RuntimeException(tmp + " is exists.");
        }
        f.copy(f2);
        if (f2.exists()) {
            f2.delete();            
        } else {
            fail();
        }
    }
    
    /**
     * {@link jp.hrtdotnet.java.io.HFile#copy(java.io.InputStream, java.io.OutputStream)} のためのテスト・メソッド。
     * @throws IOException 
     */
    public void testCopy_InputStreamOutputStream() throws IOException {
        HFile f = new HFile(testClassResources.getString("file"));
        Calendar c = Calendar.getInstance();
        DateFormat df = new SimpleDateFormat("yyyyMMddHHmmssSSS");
        File f2 = new File(tmp + df.format(c.getTime()));
        if (f2.exists()) {
            throw new RuntimeException(tmp + " is exists.");
        }
        FileInputStream in = new FileInputStream(f);
        FileOutputStream out = new FileOutputStream(f2);
        HFile.copy(in, out);
        in.close();
        out.close();
        if (f2.exists()) {
            f2.delete();            
        } else {
            fail();
        }
    }
    
    /**
     * {@link jp.hrtdotnet.java.io.HFile#copy(java.io.File, java.io.File)} のためのテスト・メソッド。
     * @throws IOException 
     */
    public void testCopy_FileFile() throws IOException {
        HFile f = new HFile(testClassResources.getString("file"));
        Calendar c = Calendar.getInstance();
        DateFormat df = new SimpleDateFormat("yyyyMMddHHmmssSSS");
        File f2 = new File(tmp + df.format(c.getTime()));
        if (f2.exists()) {
            throw new RuntimeException(tmp + " is exists.");
        }
        HFile.copy(f, f2);
        if (f2.exists()) {
            f2.delete();            
        } else {
            fail();
        }
    }

    /**
     * {@link jp.hrtdotnet.java.io.HFile#copy(java.io.File, java.io.File, boolean)} のためのテスト・メソッド。
     * @throws IOException 
     */
    public void testCopy_FileFileBoolean() throws IOException {
        HFile f = new HFile(testClassResources.getString("file"));
        Calendar c = Calendar.getInstance();
        DateFormat df = new SimpleDateFormat("yyyyMMddHHmmssSSS");
        File f2 = new File(tmp + df.format(c.getTime()));
        if (f2.exists()) {
            throw new RuntimeException(tmp + " is exists.");
        }
        HFile.copy(f, f2);
        HFile.copy(f, f2, true);

        try {
            HFile.copy(f, f2, false);
            fail();
        } catch (IOException e) {            
        }
        if (f2.exists()) {
            f2.delete();            
        } else {
            fail();
        }

    }

    /**
     * {@link jp.hrtdotnet.java.io.HFile#getExtension(java.lang.String)} のためのテスト・メソッド。
     */
    public void testGetExtensionString() {
        assertEquals(HFile.getExtension("abc.txt"),"txt");
    }


}
