package vermilion;

// TODO: High priority: Have to get this file into shape, thrown together
// while very tired.

//TODO: Create the program's sample bank, with the ability to hold audio, envelopes,
//waveforms and other things as defined by registerable classes. (Good major
//project if you are ambitious).

//TODO: Implement the loading and saving of things in the sample bank, both as part
//of a composition and as external files, including (load only) support for things
//like MP3 files. (Library work, good on resume)

//TODO: Create the supporting routines/classes for the sample bank allowing easy use
//of sampled audio, waveforms or envelopes by machine plugin developers. (Write your
//own API, with my guidance)

// TODO: Think of ways for other systems to get a handle for the sample bank,
// maybe via a system message.

import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import relative.RelativeLayout;
import relative.RelativePlacement;

/**
 * A sample bank which will be used to store and provide sample audio, envelopes,
 * and oscillators.
 */
public class SystemSampleBank extends PluginClassVermilion
{
    /**
     * The panel which we show to the user for loading and manipulating samples.
     */
    private JPanel panel;

    /**
     * The sample types that are supported by the sample bank.
     */
    private ArrayList<SampleObject> knownSampleTypes;

    /**
     * The samples that are held by the sample bank.
     */
    private SampleObject[] sampleBank;
    private DefaultListModel sampleList;
    protected JList sampleListC;
    private RelativeLayout theLayout;
    protected JButton newButton;
    protected JButton clrButton;
    protected JButton loadButton;
    protected JButton saveButton;

    /**
     * The type for this plugin is 'STARTUP'.
     */
    @Override
    public String getType()
    {
        return "STARTUP";
    }

    /**
     * The name for this plugin is 'SampleBank'.
     */
    @Override
    public String getName()
    {
        return "SampleBank";
    }

    /**
     * The initialise method of this plugin creates the interface tab.
     */
    @Override
    public void initialise()
    {
        UsefulFile.registerType(new SampleSampledAudio());

        sampleBank = new SampleObject[1000];
        knownSampleTypes = new ArrayList<SampleObject>();
        SampleBankListener sampleListener = new SampleBankListener(this);
        SampleSelectListener selectListener = new SampleSelectListener(this);

        // TODO: LIsts in composer need scrollbars.

        panel = new JPanel();
        Main.window.addTab("Samples", panel);

        theLayout = new RelativeLayout(null);
        panel.setLayout(theLayout);

        sampleList = new DefaultListModel();
        sampleListC = new JList(sampleList);
        JScrollPane listScroll = new JScrollPane(sampleListC);
        theLayout.registerForFontSizeChanges(sampleListC);
        sampleListC.addListSelectionListener(selectListener);
        panel.add(listScroll, new RelativePlacement(0, 0, 800, 400));

        loadButton = new JButton("Load");
        theLayout.registerForFontSizeChanges(loadButton);
        loadButton.addActionListener(sampleListener);
        panel.add(loadButton, new RelativePlacement(900, 0, 100, 50));

        saveButton = new JButton("Save");
        theLayout.registerForFontSizeChanges(saveButton);
        saveButton.addActionListener(sampleListener);
        panel.add(saveButton, new RelativePlacement(900, 50, 100, 50));

        newButton = new JButton("New");
        theLayout.registerForFontSizeChanges(newButton);
        newButton.addActionListener(sampleListener);
        panel.add(newButton, new RelativePlacement(900, 100, 100, 50));

        clrButton = new JButton("Clear");
        theLayout.registerForFontSizeChanges(clrButton);
        clrButton.addActionListener(sampleListener);
        panel.add(clrButton, new RelativePlacement(900, 150, 100, 50));


        JLabel aLabel = new JLabel("Coming Soon: Display and basic editing of samples.", JLabel.CENTER);
        panel.add(aLabel, new RelativePlacement(0, 400, 1000, 600));
        theLayout.registerForFontSizeChanges(aLabel, 1.0f, "", Font.ITALIC);

        refreshList();
        sampleListC.ensureIndexIsVisible(0);
        sampleListC.setSelectedIndex(0);

        Main.plugins.sendMessage("Sample Bank Ready", this);
    }

    /**
     * The deinitialise method for this plugin removes the interface tab.
     */
    @Override
    public void deinitialise()
    {
        Main.window.removeTab(panel);
    }

    /**
     * TODO: Write samples to the composition.
     */
    @Override
    public void documentSaving()
    {
    }

    /**
     * TODO: Read samples and deserialise.
     */
    @Override
    public void documentLoaded()
    {
        for (int x = 0; x < 1000; x++)
        {
            sampleBank[x] = (SampleObject) Main.document.getValue("Samples/" + x);
        }

        refreshList();
    }

    /**
     * Processes messages for this component (if any ever exist).
     * @param message A message from another system component.
     */
    @Override
    public void processMessage(String message, Object msgVal)
    {
    }

    // TODO: Don't hardcode 1000? intersystem constant?

    private void refreshList()
    {
        sampleList.clear();

        sampleList = new DefaultListModel();
        sampleList.ensureCapacity(1000);

        for (int x = 0; x < 1000; x++)
        {
            String sampleStr = x + ": ";
            if (sampleBank[x] == null) sampleList.addElement(sampleStr + "[EMPTY]");
            else sampleList.addElement(sampleStr + sampleBank[x].toString());
        }

        sampleListC.setModel(sampleList);
    }

    protected void setSample(SampleObject sample)
    {
        int sampleNum = sampleListC.getSelectedIndex();
        if (sampleNum < 0 && sampleNum >= 1000) return;

        sampleBank[sampleNum] = sample;
        Main.document.setValue("Samples/" + sampleNum, sample);

        refreshList();
        sampleListC.setSelectedIndex(sampleNum);
        sampleListC.ensureIndexIsVisible(sampleNum);
    }

    public SampleObject getSample(int index)
    {
        return sampleBank[index];
    }
}

/**
 * A listener for the buttons and menu that handles starting and stopping
 * playback, as well as pattern creation and other operations.
 */
class SampleBankListener implements ActionListener
{
    private SystemSampleBank sampleBank;

    /**
     * Constructs the composer listener with reference to composer and panel.
     */
    public SampleBankListener(SystemSampleBank owner)
    {
        sampleBank = owner;
    }

    /**
     * Handles actions from the menu and buttons for the composer interface.
     */
    @Override
    public void actionPerformed(ActionEvent e)
    {
        if (e.getSource() == sampleBank.loadButton)
        {
            String sampleFile = Main.window.getLoadFile(".wav", "*.WAV - Waveform Audio Files");
            
            // TODO: Try all known formats.
            SampleSampledAudio sample = new SampleSampledAudio();
            sample.loadFile(sampleFile);
            sampleBank.setSample(sample);
        }
    }
}

/**
 * A listener for the buttons and menu that handles starting and stopping
 * playback, as well as pattern creation and other operations.
 */
class SampleSelectListener implements ListSelectionListener
{
    private SystemSampleBank sampleBank;

    /**
     * Construct the select listener with reference to composer and panel.
     */
    public SampleSelectListener(SystemSampleBank owner)
    {
        sampleBank = owner;
    }

    /**
     * Handles actions from the list controls on the tracker panel.
     */
    @Override
    public void valueChanged(ListSelectionEvent e)
    {
        
    }
}