import java.awt.Color;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.List;
import java.util.Vector;
import java.util.Timer;
import java.util.TimerTask;
import com.denova.io.Log;
import com.denova.lang.TimeSharer;
import com.denova.ui.ButtonsIcons;
import com.denova.ui.Marquee;
import com.denova.ui.SwingCheckerThread;
import com.denova.util.DataFinder;
import com.denova.util.PropertyList;
import com.denova.JExpress.Installer.CustomInstaller;
import com.denova.ui.WizardPanel;
import javax.swing.ImageIcon;


/**
 * Start billboards after the user inputs the
 * install directory name. Each billboard is stored
 * in a plain text file called billboard?.txt, where
 * the ? is replaced with a sequential number starting
 * with 1 (e.g., billboard1.txt). The first line in the
 * text file is centered.
 *
 * You must verify that the text is not too wide for
 * the display area. You can change the image used, but
 * an image must be included or the billboards won't 
 * show. 
 *
 * You should adjust the "private final" statements at
 * the top of this file to fit your billboards (font size,
 * text color, etc.). You also can set a one line of
 * text that appears at the bottom of the image. See
 * the com.denova.ui.Billboards class for more details
 * about customizing the billboards.
 *
 * Although you can start the billboards at anytime during
 * the installation process, this class assumes you will
 * include this class "After readme". Call the static finish() 
 * method if you would like the billboards to stop and
 * redisplay the logo that usually shows during installation.
 *
 * © 2002-2011 DeNova
 * 
 *
 * Notes:
 *  1. This class must go "After selecting install dir".
 *  2. Don't forget to include the billboard.jpg and billboard*.txt
 *     files in the JExpressInstaller directory.
 *
 * Last modified: 2011-03-25
 */
public class StartBillboards extends WizardPanel
{

    private static final int SecsBtwBillboards = 30;
    private static final String ImageFilename = "billboard.jpg";
    private static final String TextPrefix = "billboard";
    private static final String TextSuffix = ".txt";
    private static final int TopMargin = 50;
    private static final int BottomMargin = 10;
    private static final int LeftMargin = 10;
    private static final int RightMargin = 10;
    private static final int FontSize = 15;
    private static final Color BackgroundColor = Color.black;
    private static final Color TextColor = Color.black;
    private static final int InitialBillboard = 1;
    
    private static Log log = null;
    
    private static int billboardIndex = InitialBillboard;
    private static boolean billboardActive = false;
    private static boolean installerFinished = false;
    
    private static Timer billboardTimer = null;


    /** Show the next billboard. */
    private class ShowBillboard extends TimerTask
    {
        public synchronized void run()
        {
            if (billboardActive)
            {
                if (installerFinished)
                {
                    stopBillboards();
                    
                    displayLogo();
                }
                
                else {
                    changeBillboard();
                }
            }
        }
    }
    
    
    /** Launch billboards. */
    private class Launch extends TimerTask
                        implements Runnable
    {
        public synchronized void run()
        {
            try {
                launchBillboards();
            }
            
            catch (Exception e) {
                logMessage("unable to start billboards");
            }
        }
    }
    
    
    /**
     *Constructor for the StartBillboards object.
     *
     * @param  properties    installer's properties.
     */
    public StartBillboards(PropertyList properties)
    {
        super(properties);
    }


    /** 
     * Enter the panel. 
     *
     * Do not call this method; only the wizard should call it.
     */
    public synchronized void enter()
    {
        showNextPanel();
    }


    /**
     *  Gets the name.
     *
     * @return    name
     */
    public String getName()
    {
        return "StartBillboards";
    }


    /**
     * Verifies that everything's ok.
     *
     * @return    true iff ready to continue with installation.
     */
    public boolean isOk()
    {
        boolean ok = super.isOk();

        // only change the properties if it's not a silent install
        if (ok)
        {
            Launch launch = new Launch();
            new SwingCheckerThread(launch).start();
        }

        return ok;
    }

    
    /** If user cancels the installer, stop the billboards. */
    public void userCanceled()
    {
        stopBillboards();
    }
    
    
    /**
     * Notify that the installer is finished.
     *
     * On the next timer tick, stop displaying 
     * the billboards and redisplay the logo.
     */
    public static void finish()
    {
        installerFinished = true;
        logMessage("billboards finished");
    }


    private void launchBillboards()
    {
        logMessage("starting billboards");

        if (billboardTimer == null)
        {
            final int OneSecond = 1000;
            
            int secsToDelay = SecsBtwBillboards * OneSecond;
            
            billboardTimer = new Timer();
            billboardTimer.schedule(new ShowBillboard(), secsToDelay, secsToDelay);
            logMessage("started billboard timer");

            billboardActive = true;            
            
            changeBillboard();
        }
    }
    
    
    private void changeBillboard()
    {
        try {
            ButtonsIcons buttonsIcons = new ButtonsIcons();
            ImageIcon imageIcon = buttonsIcons.getIcon(ImageFilename);
            if (imageIcon == null)
            {
                logMessage("unable to find " + ImageFilename);
                
                billboardActive = false;
                stopBillboards();
                
                logMessage("stopped updating billboard");
            }
            
            else {
                String textFilename = TextPrefix + billboardIndex + TextSuffix;
                InputStream input = getClass().getResourceAsStream(textFilename);
                //InputStream input = DataFinder.getStream(textFilename);
                if (input == null)
                {
                    displayLogo();
                    
                    // setup to start the billboards again
                    billboardIndex = InitialBillboard;
                    
                    logMessage("ready to restart billboards");
                }
                
                else
                {
                    List text = getText(textFilename, input);
                    input.close();
                    
                    updateBillboard(ImageFilename, text);
                    ++billboardIndex;
                }
            }
        }
        
        catch (Exception e) {
            logException(e);
        }
    }
    
    
    private void updateBillboard(String imageFilename,
                               List text)
    {
        Marquee window = CustomInstaller.getMarquee();
        window.setBackgroundFilename(imageFilename);
        window.setText(text);
        window.setTextColor(TextColor);
        window.setTopMargin(TopMargin);
        window.setBottomMargin(BottomMargin);
        window.setLeftMargin(LeftMargin);
        window.setRightMargin(RightMargin);
        window.setFontSize(FontSize);
        
        CustomInstaller.updateMarquee(window);
        logMessage("displayed billboard " + billboardIndex);
    }
    
    
    private static void displayLogo()
    {
        Marquee window = CustomInstaller.getMarquee();
        window.setBackgroundFilename(CustomInstaller.getImageFilename());
        window.setText(null);
        window.setFontSize(0);
        
        CustomInstaller.updateMarquee(window);
        logMessage("displayed logo");
    }
    
    
    private static void stopBillboards()
    {
        if (billboardTimer != null)
        {
            billboardTimer.cancel();
            
            Timer pmdNull = null;
            billboardTimer = pmdNull;
            logMessage("stopped billboards");
        }
    }
    
    
    private List getText(String textFilename,
                         InputStream fIn)
    {
        List text = new Vector();
        
        try
        {
            BufferedReader in = 
              new BufferedReader(new InputStreamReader(fIn));

            String line = in.readLine();
            while (line != null)
            {
                text.add(line.trim());
                line = in.readLine();
                TimeSharer.yield();
            }

            in.close();

            logMessage("got text from: " + textFilename);
        }
        
        catch (Exception e)
        {
            logMessage("unable to get text");
            logException(e);
        }
        
        return text;
    }

    
    private static void logMessage(String message)
    {
        startLogging();
        log.write(message);
    }


    private static void logException(Exception e)
    {
        startLogging();
        log.write(e);
    }


    private static void startLogging()
    {
        if (log == null)
        {
            log = new Log("billboards");
        }
    }

} // StartBillboards