/*
 * Copyright (C) 2005 - 2011 Jaspersoft Corporation. All rights reserved.
 * http://www.jaspersoft.com.
 *
 * Unless you have purchased  a commercial license agreement from Jaspersoft,
 * the following license terms  apply:
 *
 * This program is free software: you can redistribute it and/or  modify
 * it under the terms of the GNU Affero General Public License  as
 * published by the Free Software Foundation, either version 3 of  the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Affero  General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public  License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
package com.jaspersoft.jasperserver.irplugin;


import com.jaspersoft.jasperserver.irplugin.gui.JRPluginConfigurationDialog;
import com.jaspersoft.jasperserver.irplugin.gui.RepositoryExplorer;
import it.businesslogic.ireport.gui.MainFrame;
import it.businesslogic.ireport.gui.sheet.Tag;
import it.businesslogic.ireport.util.I18n;
import it.businesslogic.ireport.util.LanguageChangedEvent;
import it.businesslogic.ireport.util.LanguageChangedListener;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;

/**
 *
 * @author  Administrator
 */
public class IRPlugin extends it.businesslogic.ireport.plugin.IReportPlugin {
    
    public static String configFileName = "jasperserverplugin.xml";
    
    /**
     * REQUIRED_VERSION and CURRENT_VERSION are set using a property file.
     */
    public static String REQUIRED_VERSION = ""; 
    public static String CURRENT_VERSION = "";
    public static final String PROPERTY_CHECK_FOR_UPDATE = "PROPERTY_CHECK_FOR_UPDATE";
    public static final String PROPERTY_USE_PROXY = "PROPERTY_USE_PROXY";
    public static final String PROPERTY_PROXY_URL = "PROPERTY_PROXY_URL";
    public static final String PROPERTY_PROXY_USE_AUTH = "PROPERTY_PROXY_USE_AUTH";
    public static final String PROPERTY_PROXY_USERNAME = "PROPERTY_PROXY_USERNAME";
    public static final String PROPERTY_PROXY_PASSWORD = "PROPERTY_PROXY_PASSWORD";
    
    private boolean viewVisible = false;
    
    private boolean firstTime = true;
    
    /**
     * I8n variables
     */
    public static final String localPackageName = "com/jaspersoft/jasperserver/irplugin/locale/";
    public static final String baseName = "irplugin";
    private static java.util.ResourceBundle oLanguage = null;
    private static Locale pluginLocale = null;
    
    private static IRPlugin mainInstance = null;
    public static IRPlugin getMainInstance() {
        return mainInstance;
    }
    
    /** This is the complete list of servers available on the tree.
     *  After an add or a remove, please save the configuration and update
     *  the repositoryExplorer.
     */
    private java.util.List jServers = new java.util.ArrayList();
    
    /**
     * Properties are stored in the user home directory under .ireport/jasperserverplugin.xml
     */
    private java.util.Properties properties = new java.util.Properties();
    
    /**
     * Properties are taken from /com/jaspersoft/jasperserver/irplugin/default.jasperserver_irplugin.properties
     * Properties can be overridden with a file called:
     * /com/jaspersoft/jasperserver/irplugin/irplugin.properties.
     * if it is not found, it will use:
     * jasperserver_irplugin.properties.
     */
    private java.util.Properties brandingProperties = new java.util.Properties();
    
    private RepositoryExplorer repositoryExplorer = null;
    boolean firstCall = true;
    
    /** Creates a new instance of HelloWorld */
    public IRPlugin() {
        mainInstance = this;
    }
    
    public void call() {
        
        // checkIReportVersion();
        if (getRepositoryExplorer() == null)
        {
             loadConfiguration();
             setRepositoryExplorer(new RepositoryExplorer(this));
             IRPlugin.getMainInstance().applyProxySettings();
        }
        
        if (MainFrame.getMainInstance().constTitle.compareTo("iReport 1.2.6 ") < 0)
         {
         //    try {
         //        
         //        getMainFrame().getDockingContainerLeft().insertPanel(0,"JasperServer",getRepositoryExplorer(), DockingContainer.INSERT_MODE_SHAREDPOSTION,true);
         //        
         //    } catch (Exception ex) { };

            
             SwingUtilities.invokeLater( new Runnable()
             {
                 public void run()
                 {
                     JOptionPane.showMessageDialog(MainFrame.getMainInstance(), getFormattedString("messages.requirements", "JasperReports plugin requires iReport {0} or above!", new Object[] {"1.2.6"}));
                 }
             });
             return;
        }
        else
        {
            if (!isViewVisible() || getRepositoryExplorer().isShowing() == false)
            {
                DockingUtil.installUI(getRepositoryExplorer());   
            }
        }
        
        if (!firstTime || getProperties().getProperty(PROPERTY_CHECK_FOR_UPDATE, "true").equals("true"))
        {
            SwingUtilities.invokeLater( new Runnable()
            {
            
                public void run()
                {
                    try {
                            UpgradeSearch us = new UpgradeSearch();
                            Thread t = new Thread(us);
                            t.start();
                        } catch (Throwable ex) {
                            ex.printStackTrace();	
                        }
                }
            });
       }
       
        if (!firstTime)
        {
            pluginLocale = I18n.getCurrentLocale();
            
            // Register itself to locale changes...
            I18n.addOnLanguageChangedListener(new LanguageChangedListener() {
                public void languageChanged(LanguageChangedEvent languageChangedEvent) {
                    // Change the servers locale...
                    for (int i=0; i<getJServers().size(); ++i)
                    {
                       ((JServer)getJServers().get(i)).setLocale(  languageChangedEvent.getLocale().getLanguage() );
                    }
                }
            });
        }
       firstTime = false;
        
    }
    
    
    
    public void configure() {
        
        JRPluginConfigurationDialog cup = new JRPluginConfigurationDialog(getMainFrame(), true);
        cup.setVisible(true);
    }
    
    
    public void applyProxySettings()
    {
        java.util.Properties props = IRPlugin.getMainInstance().getProperties();
        
        System.getProperties().remove("proxySet");
        System.getProperties().remove("proxyHost");
        System.getProperties().remove("proxyPort");
        System.getProperties().remove("http.proxyHost");
        System.getProperties().remove("http.proxyPort");
        System.getProperties().remove("http.proxyUser");
        System.getProperties().remove("http.proxyPassword");
        System.getProperties().remove("https.proxyHost");
        System.getProperties().remove("https.proxyPort");
              
        if (props.getProperty(IRPlugin.PROPERTY_USE_PROXY, "false").equals("true"))
        {
            //System.getProperties().put( "proxySet", "true" );

            String urlProxy = props.getProperty(IRPlugin.PROPERTY_PROXY_URL, "");
            String port = "8080";
            String server = urlProxy;
            if (urlProxy.indexOf(":") > 0)
            {
                port = urlProxy.substring(urlProxy.indexOf(":") + 1);
                server = urlProxy.substring(0, urlProxy.indexOf(":"));
            }

            System.getProperties().put( "http.proxyHost", server );
            System.getProperties().put( "http.proxyPort", port );
            //System.getProperties().put( "proxyHost", server );
            //System.getProperties().put( "proxyPort", port );
            
            if (props.getProperty(IRPlugin.PROPERTY_PROXY_USE_AUTH, "false").equals("true"))
            {
                String userName = props.getProperty(IRPlugin.PROPERTY_PROXY_USERNAME, "");
                String userPass = props.getProperty(IRPlugin.PROPERTY_PROXY_PASSWORD, "");
                System.getProperties().put( "http.proxyUser", userName );
                System.getProperties().put( "http.proxyPassword", userPass );
            }
        }
    }
    
    
    /**
     * Load the plugin configuration from IREPORT_USER_HOME_DIR/jasperserverplugin.xml
     */
    public void loadConfiguration()
    {
       
            setProperties(new java.util.Properties());
            java.io.File configFile = new java.io.File(it.businesslogic.ireport.gui.MainFrame.IREPORT_USER_HOME_DIR, configFileName);
            try {
                if (configFile.exists()) {
                    getProperties().loadFromXML(new java.io.FileInputStream(configFile));
                }
            } catch (java.lang.Exception ex) {
                ex.printStackTrace();
            }
            java.util.Properties props = getProperties();
            for (int i = 0; props.getProperty("server." + i + ".name") != null; ++i) {
                com.jaspersoft.jasperserver.irplugin.JServer server = new com.jaspersoft.jasperserver.irplugin.JServer();
                server.setName(props.getProperty("server." + i + ".name"));
                server.setUrl(props.getProperty("server." + i + ".url"));
                server.setUsername(props.getProperty("server." + i + ".username"));
                String pwd = null;
                if (props.getProperty("server." + i + ".password.enc") != null)
                {
                    Encrypter enc = new Encrypter(getBrandingProperties().getProperty("irplugin.encrypt.passwords.key","54fj245vn3vfdsmce4mg0jvs"));
                    pwd = enc.decrypt(props.getProperty("server." + i + ".password.enc"));
                }
                else
                {
                    pwd = props.getProperty("server." + i + ".password");
                }
                server.setPassword(pwd);
                server.setLocale(it.businesslogic.ireport.util.I18n.getCurrentLocale().getLanguage());
                getJServers().add(server);
            }
            addProperties("/com/jaspersoft/jasperserver/irplugin/default.jasperserver_irplugin.properties", getBrandingProperties());
            addProperties("/com/jaspersoft/jasperserver/irplugin/jasperserver_irplugin.properties", getBrandingProperties());
            java.lang.System.out.println(getBrandingProperties() + "");
            REQUIRED_VERSION = getBrandingProperties().getProperty("irplugin.server.required.version");
            CURRENT_VERSION = getBrandingProperties().getProperty("irplugin.version");
            
             try {
                    Method m = it.businesslogic.ireport.gui.MainFrame.class.getMethod("addLinkType", new Class[]{java.lang.String.class});
                    m.invoke( it.businesslogic.ireport.gui.MainFrame.getMainInstance(), new Object[]{ "ReportExecution" });
            } catch (NoSuchMethodException ex) {
            } catch (IllegalAccessException ex) {
            } catch (InvocationTargetException ex) {
            } catch (SecurityException ex) {
            }
    }
    
    private void addProperties(String resourceUri, java.util.Properties props)
    {
        try {
            
            InputStream is = this.getClass().getResourceAsStream(resourceUri);
            if (is == null) return;
            props.load( is );
        } catch (Exception ex)
        {
            ex.printStackTrace();
        }      
    }
    
    /**
     * Save the plugin configuration in IREPORT_USER_HOME_DIR/jasperserverplugin.xml
     */
    public boolean saveConfiguration()
    {
        File dir = new File( MainFrame.IREPORT_USER_HOME_DIR );
        
        // Update all informations about servers...
        // 1. remove all server.X tags...
        // 2. add all server configurations...
        for (int i=0; getProperties().getProperty("server."+i+".name") != null; ++i)
        {
            getProperties().remove("server."+i+".name");
            getProperties().remove("server."+i+".url");
            getProperties().remove("server."+i+".username");
            getProperties().remove("server."+i+".password");
            getProperties().remove("server."+i+".password.enc");
        }
        
        for (int i=0; i<getJServers().size(); ++i)
        {
            JServer server = (JServer)getJServers().get(i);
            getProperties().setProperty("server."+i+".name", server.getName());
            getProperties().setProperty("server."+i+".url", server.getUrl());
            getProperties().setProperty("server."+i+".username", server.getUsername());
            
            if (getBrandingProperties().getProperty("irplugin.encrypt.passwords", "true").equals("true"))
            {
                Encrypter enc = new Encrypter(getBrandingProperties().getProperty("irplugin.encrypt.passwords.key","54fj245vn3vfdsmce4mg0jvs"));
                getProperties().setProperty("server."+i+".password.enc", enc.encrypt(server.getPassword()));
            }
            else
            {
                getProperties().setProperty("server."+i+".password", server.getPassword());
            }
        }
        
        try {
            if (dir.exists()) {
                if (!dir.isDirectory() ) {
                    javax.swing.JOptionPane.showMessageDialog( getMainFrame(), 
                            getFormattedString("messages.error.1", 
                                               "{0}\nis not a directory!\nPlease rename this file and retry to save config!", 
                                               new Object[] {""+dir.getPath()}),
                            "",JOptionPane.ERROR_MESSAGE);
                    return false;
                }
            }
            else {
                dir.mkdirs();
            }
            
            File configFile = new File(dir,configFileName);
            getProperties().storeToXML(new FileOutputStream(configFile),"JasperServer Plugin configuration file\n (c) 2006 by JasperSoft");
            
            return true;
        } catch (Exception ex) {
            javax.swing.JOptionPane.showMessageDialog(  getMainFrame(),
                    getFormattedString("messages.error.2", 
                                               "An error is occurred saving Plugin config:\n{0}\nPlease try to save config again!", 
                                               new Object[] {""+ex.getMessage()}),
                            "",JOptionPane.ERROR_MESSAGE);
                    
            return false;
        }
    }

    /**
     * Get Plugin properties
     */
    public java.util.Properties getProperties() {
        return properties;
    }

    /**
     * Set Plugin properties (this nethod should be never used....
     */
    public void setProperties(java.util.Properties properties) {
        this.properties = properties;
    }

    public java.util.List getJServers() {
        return jServers;
    }

    public void setJServers(java.util.List jServers) {
        this.jServers = jServers;
    }
    
    /**
     * Create a tmp file name. A complete path name is returned.
     * The location of the file is the "jstmp" directory inside
     * the IREPORT_USER_HOME_DIR
     * (i.e. C:\Documents and Settings\gtoffoli\.ireport\jstmp\...)
     * If this directory does not exist, it is created.
     *  
     * filePrefix (can be null)
     * fileExtension (can be null, default ".tmp")
     *
     * The caller is responsable for delation of this files.
     * No check if the file already exists is performed.
     */
    public static String createTmpFileName(String filePrefix, String fileExtension)
    {
            if (filePrefix == null) filePrefix = "";
            else filePrefix += "_";
            if (fileExtension != null && !fileExtension.startsWith("."))
            {
                fileExtension = "." + fileExtension;
            }
            
            if (fileExtension == null) fileExtension = ".tmp";
            
            String tmpDirectory = MainFrame.getMainInstance().IREPORT_USER_HOME_DIR;
            tmpDirectory += File.separator + "jstmp";
            
            File tmpDirectoryFile = new File(tmpDirectory);
            if (!tmpDirectoryFile.exists())
            {
                tmpDirectoryFile.mkdirs();
            }
            
            return tmpDirectoryFile + File.separator + filePrefix + (new java.util.Date()).getTime() + fileExtension;
            
    }

    public RepositoryExplorer getRepositoryExplorer() {
        return repositoryExplorer;
    }

    public void setRepositoryExplorer(RepositoryExplorer repositoryExplorer) {
        this.repositoryExplorer = repositoryExplorer;
    }

    public boolean isViewVisible() {
        return viewVisible ;
    }

    public void setViewVisible(boolean viewVisible) {
        this.viewVisible = viewVisible;
    }
    
    /********************** I18n utilities.... *******************/
    public static String getString(String cID,String defaultValue)
    {
        return getString(cID, I18n.getCurrentLocale(), defaultValue );
    }
 
    public static String getFormattedString(String cID, String defaultValue, Object[] args)
    {
        String pattern = getString(cID, I18n.getCurrentLocale(), defaultValue );
        java.text.MessageFormat mf = new java.text.MessageFormat(pattern, I18n.getCurrentLocale());
        return mf.format(args);
    }
    
    private static String getString(String cID, Locale currentLocale, String defaultValue)
    {
        try
        {
            if(oLanguage == null || !pluginLocale.equals( currentLocale ))
            {
                pluginLocale = currentLocale;
                oLanguage = java.util.ResourceBundle.getBundle( localPackageName + baseName,
                        currentLocale);
            }
            String s = oLanguage.getString(cID);
            if (s != null && s.startsWith("${") && s.endsWith("}") )
            {
                String newKey = s.substring(2, s.length()-1);
                if (newKey.length() > 0)
                {
                    return I18n.getString(newKey, defaultValue);
                }
            }
            
            return s;
        }
        catch (MissingResourceException ex)
        {
            System.out.println("IRPlugin: Can't find the translation for key = " + cID +": using default (" + defaultValue + ")");
        }
        catch (Exception ex)
        {
            System.out.println("IRPlugin: Exception loading cID = " + cID +": " + ex.getMessage());
        }
        return defaultValue;
    }

    public static java.util.ResourceBundle getOLanguage() {
        return oLanguage;
    }

    public static void setOLanguage(java.util.ResourceBundle aOLanguage) {
        oLanguage = aOLanguage;
    }

    public java.util.Properties getBrandingProperties() {
        return brandingProperties;
    }

    public void setBrandingProperties(java.util.Properties brandingProperties) {
        this.brandingProperties = brandingProperties;
    }
    
    /**
     * Returns the languages configured in the BrandingProperties
     */
    public List getSupportedQueryLanguages()
    {
        Iterator iter = getBrandingProperties().keySet().iterator();
        java.util.ArrayList list = new java.util.ArrayList();
        
        while (iter.hasNext())
        {
            String key = ""+iter.next();
            if (key.startsWith("query.language.") && !key.endsWith(".enabled"))
            {
                String language = key.substring(15);
                if ( getBrandingProperties().getProperty(key + ".enabled","true").equals("true") )
                {
                    list.add( new Tag(language, getBrandingProperties().getProperty(key) ) );
                }
            }
        }
        
        // Sorting list...
        Object[] tobeordered = list.toArray();
        Arrays.sort(tobeordered, new Comparator() {
            public int compare(Object o1, Object o2) {
            
               return ((Tag)o1).getName().compareTo( ((Tag)o2).getName() );
            }
            public boolean equals(Object obj) {
               return (obj != null && this.equals(obj) );
            }
        } );
        
        list.clear();
        for (int i=0; i<tobeordered.length; ++i) list.add(tobeordered[i]);
        
        return list;
    }


    /**
     *  This method validates URL like:
     *
     *  123.123.123[:port]
     *  domain.domain.dom[:port]
     *
     */
    public static boolean isValidUrl(String url) 
    { 
        String strRegex = 
         "((([0-9]{1,3}\\.){3})[0-9]{1,3})" + // IP- 199.194.52.184 
         "|" + // allows either IP or domain 
         "(([0-9a-z][0-9a-z-]{0,61})?[0-9a-z]\\.?)++" + // domain pice 
         "(:[0-9]{1,4})?"; // port number- :80 
         
         return url.matches( strRegex );
    } 
}




