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

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

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.List;

import com.ibm.icu.dev.test.serializable.SerializableTestUtility.Handler;
import com.ibm.icu.util.TimeZone;
import com.ibm.icu.util.VersionInfo;

/**
 * This class writes the test objects for each class to a file. The work is
 * actually done by the superclass, CoverageTest. This class just constructs
 * a CoverageTest w/ a non-null path, which tells it to write the data.
 *
 */
public class SerializableWriter
{
    String path;

    public SerializableWriter(String path)
    {
        this.path = path;
    }

    private static String folderName()
    {
        int major = VersionInfo.ICU_VERSION.getMajor();
        int minor = VersionInfo.ICU_VERSION.getMinor();
        int milli = VersionInfo.ICU_VERSION.getMilli();
        int micro = VersionInfo.ICU_VERSION.getMicro();
        StringBuffer result = new StringBuffer("ICU_");

        result.append(major);
        result.append(".");
        result.append(minor);

        if (milli != 0 || micro != 0) {
            result.append(".");
            result.append(milli);

            if (micro != 0) {
                result.append(".");
                result.append(micro);
            }
        }

        return result.toString();
    }

    public static void main(String[] args) throws IOException
    {
        String outDir = null;
        if (args.length == 0) {
            URL dataURL = SerializableWriter.class.getResource("data");
            outDir = dataURL.getPath() + "/" + folderName();
        } else {
            outDir = args[0] + "/" + folderName();
        }

        // Override default TimeZone, so serialized data always use
        // the consistent zone if not specified.
        TimeZone.setDefault(TimeZone.getTimeZone("America/Los_Angeles"));

        SerializableWriter writer = new SerializableWriter(outDir);

        writer.serialize();
    }

    public void serialize() throws IOException {
        File outDir = new File(this.path);
        if (!outDir.exists()) {
            outDir.mkdirs();
        }

        List<String> classList = SerializableTestUtility.getSerializationClassList(this);
        for (String className : classList) {
            Handler classHandler = SerializableTestUtility.getHandler(className);
            if (classHandler == null) {
                System.out.println("No Handler - Skipping Class: " + className);
                continue;
            }
            Object[] testObjects = classHandler.getTestObjects();
            File oof = new File(this.path, className + ".dat");
            SerializableTestUtility.serializeObjects(oof, testObjects);
        }
    }
}
