/*
 * 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 itest;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.StringTokenizer;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;

import junit.framework.TestCase;

public class LicenseTestCase extends TestCase {

    // TODO: turn this in to a maven plugin that can be run from the module that builds the archive
    
    public void testCreateComponent() throws ZipException, IOException {

        File archive = new File("..\\..\\distribution\\target\\apache-tuscany-sca-1.6.1-SNAPSHOT.zip");
        ZipFile zf = new ZipFile(archive);
        try {

            String licenstText = getLicenseText(zf);
            List<String> jarsInArchive = getJarsInDistro(zf);

            List<String> jarsNotInLicense = getJarsNotInLicense(licenstText, jarsInArchive);
            if (jarsNotInLicense.size() > 0) {
                System.out.println("jarsNotInLicense: " + jarsNotInLicense);
            }

            List<String> jarsNotInArchive = getJarsNotInArchive(licenstText, jarsInArchive);
            if (jarsNotInArchive.size() > 0) {
                System.out.println("jarsNotInArchive: " + jarsNotInArchive);
            }
            
            assertTrue("License errors, check log for details", jarsNotInArchive.size()==0 && jarsNotInLicense.size()==0);

        } finally {
            zf.close();
        }
    }

    private List<String> getJarsNotInLicense(String licenstText, List<String> jarsInArchive) {
        List<String> jarsNotInLicense = new ArrayList<String>();
        for (String jarName : jarsInArchive) {
            if (!licenseHasJar(licenstText, jarName)) {
                jarsNotInLicense.add(jarName);
            }
        }
        return jarsNotInLicense;
    }

    private List<String> getJarsNotInArchive(String licenstText, List<String> jarsInArchive) throws IOException {
        List<String> jarsNotInArchive = new ArrayList<String>();
        BufferedReader reader = new BufferedReader(new StringReader(licenstText));
        String line = null;
        while ((line = reader.readLine()) != null) {
            line = line.trim();
            if (line.contains(".jar")) {
                StringTokenizer st = new StringTokenizer(line);
                while (st.hasMoreTokens()) {
                    String s = st.nextToken();
                    if (s.contains(".jar")) {
                        if (s.startsWith("(")) {
                            s = s.substring(1);
                        }
                        if (s.endsWith(",") || s.endsWith(":")) {
                            s = s.substring(0, s.length()-1);
                        }
                        if (s.endsWith(")")) {
                            s = s.substring(0, s.length()-1);
                        }
                        if (!jarsInArchive.contains(s) && !s.startsWith("tuscany-")) {
                            jarsNotInArchive.add(s);
                        }
                    }
                }
            }
        }
        return jarsNotInArchive;
    }

    private boolean licenseHasJar(String licenstText, String jarName) {
        // TODO: be good to make these configurable, maybe system props that can
        // be configured in the pom.xml?
        if (jarName.startsWith("tuscany-")) {
            return true;
        } else if (jarName.startsWith("demo-bigbank")) {
            return true;
        } else if (jarName.startsWith("tutorial-")) {
            return true;
        } else if (jarName.startsWith("sample-")) {
            return true;
        } else {
            return licenstText.indexOf(jarName) > -1;
        }
    }

    private String getLicenseText(ZipFile zf) throws IOException {
        ZipEntry ze = zf.getEntry("tuscany-sca-1.6.1-SNAPSHOT/LICENSE");
        InputStream in = zf.getInputStream(ze);
        String l = readLICENSE(in);
        return l;
    }

    private List<String> getJarsInDistro(ZipFile zf) {
        ZipEntry ze;
        List<String> jarsInArchive = new ArrayList<String>();
        for (Enumeration<? extends ZipEntry> e = zf.entries(); e.hasMoreElements();) {
            ze = e.nextElement();
            String name = ze.getName();
            if (name.endsWith(".jar")) {
                if (name.lastIndexOf('/') > -1){
                    name = name.substring(name.lastIndexOf('/')+1);
                }
                jarsInArchive.add(name);
            }
        }
        System.out.println("jarsInArchive: " + jarsInArchive.size());
        return jarsInArchive;
    }

    private static String readLICENSE(InputStream in) throws java.io.IOException {
        StringBuffer fileData = new StringBuffer();
        BufferedReader reader = new BufferedReader(new InputStreamReader(in));
        char[] buf = new char[16384];
        int numRead = 0;
        while ((numRead = reader.read(buf)) != -1) {
            String readData = String.valueOf(buf, 0, numRead);
            fileData.append(readData);
            buf = new char[16384];
        }
        reader.close();
        return fileData.toString();
    }
}
