// © 2016 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html#License
/*
 *******************************************************************************
 * Copyright (C) 1996-2016, International Business Machines Corporation and
 * others. All Rights Reserved.
 *******************************************************************************
 *
 */

package com.ibm.icu.dev.test.serializable;

import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.JarURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

import org.junit.Test;
import org.junit.runner.RunWith;

import com.ibm.icu.dev.test.TestFmwk;
import com.ibm.icu.dev.test.serializable.SerializableTestUtility.Handler;

import junitparams.JUnitParamsRunner;
import junitparams.Parameters;

/**
 * @author sgill
 * @author emader
 */
@RunWith(JUnitParamsRunner.class)
public class CompatibilityTest extends TestFmwk
{
    private static final class FileHolder {
        String className;
        String icuVersion;
        byte[] b;
        boolean skip;

        FileHolder(String fileName, byte[] b) {
            this.b = b;

            // Replace '\' with '/' to normalize fileName before extracting
            // substrings. This is required if serialization test data is
            // loaded from Windows file system.
            String tmpPath = fileName.replaceAll("\\\\", "/");

            int fileBreak = tmpPath.lastIndexOf('/');
            this.className = fileName.substring(fileBreak + 1, tmpPath.lastIndexOf('.'));
            int finalDirBreak = tmpPath.lastIndexOf("/ICU");
            this.icuVersion = tmpPath.substring(finalDirBreak + 1, fileBreak);
            className = className.substring(className.lastIndexOf('/') + 1);

            this.skip = skipFile(this.icuVersion, this.className);
        }

        private static boolean skipFile(String icuVersion, String className) {
            for (int skip = 0; skip < SKIP_CASES.length; skip++) {
                if (icuVersion.equals(SKIP_CASES[skip][0]) && className.equals(SKIP_CASES[skip][1])) {
                    return true;
                }
            }
            return false;
        }

        @Override
        public String toString() {
            return icuVersion + "[" + className + "]";
        }
    }

    @Test
    @Parameters(method="generateClassList")
    public void testCompatibility(FileHolder holder) throws ClassNotFoundException, IOException {
        if (holder.skip) {
            logln("Skipping File = " + holder);
            return;
        }

        Object[] oldObjects = SerializableTestUtility.getSerializedObjects(holder.b);
        Handler classHandler = SerializableTestUtility.getHandler(holder.className);

        Object[] testObjects = classHandler.getTestObjects();
        for (int i = 0; i < testObjects.length; i++) {
            if (!classHandler.hasSameBehavior(oldObjects[i], testObjects[i])) {
                errln("Input object " + i + ", className " + holder.className + ": failed behavior test.");
            }
        }
    }

    /**
     * The path to an actual data resource file in the JAR. This is needed because when the
     * code is packaged for Android the resulting archive does not have entries for directories
     * and so only actual resources can be found.
     */
    private static final String ACTUAL_RESOURCE = "/ICU_3.6/com.ibm.icu.impl.OlsonTimeZone.dat";

    @SuppressWarnings("unused")
    private List<FileHolder> generateClassList() throws IOException {
        // Get the URL to an actual resource and then compute the URL to the directory just in
        // case the resources are in a JAR file that doesn't have entries for directories.
        URL dataURL = getClass().getResource("data" + ACTUAL_RESOURCE);
        try {
            dataURL = new URL(dataURL.toExternalForm().replace(ACTUAL_RESOURCE, ""));
        } catch (MalformedURLException e) {
            throw new RuntimeException(e);
        }
        String protocol = dataURL.getProtocol();

        if (protocol.equals("jar")) {
            return getJarList(dataURL);
        } else if (protocol.equals("file")) {
            return getFileList(dataURL);
        } else {
            errln("Don't know how to test " + dataURL);
            return null;
        }
    }

    private List<FileHolder> getFileList(URL dataURL) throws IOException {
        List<FileHolder> classList = new ArrayList();

        File topDir = new File(dataURL.getPath());
        File dataDirs[] = topDir.listFiles(new FileFilter() {
            @Override
            public boolean accept(File pathname) {
                return pathname.isDirectory();
            }});

        for (File dataDir : dataDirs) {
            File files[] = dataDir.listFiles(new FileFilter() {
                @Override
                public boolean accept(File pathname) {
                    return pathname.isFile() && pathname.getName().endsWith(".dat");
                }});

                for (File file : files) {
                    FileInputStream fis = new FileInputStream(file);
                    byte[] fileBytes;
                    try {
                        fileBytes = SerializableTestUtility.copyStreamBytes(fis);
                    } finally {
                        fis.close();
                    }
                    classList.add(new FileHolder(file.getAbsolutePath(), fileBytes));
                }
        }
        return classList;
    }

    private List<FileHolder> getJarList(URL jarURL) throws IOException {
        List<FileHolder> classList = new ArrayList();

        String prefix = jarURL.getPath();
        int ix = prefix.indexOf("!/");
        if (ix >= 0) {
            prefix = prefix.substring(ix + 2);
        }

        JarFile jarFile = null;
        try {
            // Need to trim the directory off the JAR entry before opening the connection otherwise
            // it could fail as it will try and find the entry within the JAR which may not exist.
            String urlAsString = jarURL.toExternalForm();
            ix = urlAsString.indexOf("!/");
            jarURL = new URL(urlAsString.substring(0, ix + 2));

            JarURLConnection conn = (JarURLConnection) jarURL.openConnection();
            jarFile = conn.getJarFile();
            Enumeration entries = jarFile.entries();
            while (entries.hasMoreElements()) {
                JarEntry entry = (JarEntry) entries.nextElement();
                if (!entry.isDirectory()) {
                    String entryName = entry.getName();

                    if (entryName.startsWith(prefix) && entryName.endsWith(".dat")) {
                        FileHolder holder = new FileHolder(entryName,
                                SerializableTestUtility.copyStreamBytes(jarFile.getInputStream(entry)));
                        classList.add(holder);

                    }
                }
            }
        } finally {
            if (jarFile != null) {
                jarFile.close();
            }
        }
        return classList;
    }

    private static final String[][] SKIP_CASES = {
            // ICU 52+ PluralRules/PluralFormat/CurrencyPluralInfo are not
            // serialization-compatible with previous versions.
            {"ICU_50.1", "com.ibm.icu.text.CurrencyPluralInfo"},
            {"ICU_51.1", "com.ibm.icu.text.CurrencyPluralInfo"},

            {"ICU_50.1", "com.ibm.icu.text.PluralFormat"},
            {"ICU_51.1", "com.ibm.icu.text.PluralFormat"},

            {"ICU_50.1", "com.ibm.icu.text.PluralRules"},
            {"ICU_51.1", "com.ibm.icu.text.PluralRules"},

            // GeneralMeasureFormat was in technical preview, but is going away after ICU 52.1.
            {"ICU_52.1", "com.ibm.icu.text.GeneralMeasureFormat"},

            // RuleBasedNumberFormat
            {"ICU_3.6",     "com.ibm.icu.text.RuleBasedNumberFormat"},

            // ICU 4.8+ MessageFormat is not serialization-compatible with previous versions.
            {"ICU_3.6",     "com.ibm.icu.text.MessageFormat"},
    };
}
