/*
 * WANDORA
 * Knowledge Extraction, Management, and Publishing Application
 * http://wandora.org
 *
 * Copyright (C) 2004-2016 Wandora Team
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

package org.wandora.application.tools.extractors.freebase;

import java.awt.Component;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Iterator;
import javax.swing.DefaultListModel;
import javax.swing.JDialog;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.wandora.application.Wandora;
import org.wandora.application.WandoraTool;
import org.wandora.application.contexts.Context;
import org.wandora.application.gui.UIBox;
import org.wandora.application.gui.simple.*;
import org.wandora.topicmap.Topic;
import org.wandora.topicmap.TopicMapException;
import org.wandora.utils.IObox;

/**
 *
 * @author
 * Eero Lehtonen
 */


public class FreebaseExtractorUI extends javax.swing.JPanel {
    
    private Wandora wandora = null;
    private boolean accepted = false;
    private JDialog dialog = null;
    private Context context = null;
    public static final String FREEBASE_MQL_API_BASE = "http://api.freebase.com/api/service/mqlread";
    public static int maxDepth = 1;
    public static int maxExtractCount = 1500;
    public static boolean toggleLimit = false;
    private ArrayList<String> searchListIds;
  /*
   * Creates new form FreebaseExtractorUI
   */
    
    public FreebaseExtractorUI() {
        initComponents();
    }
    
    public boolean wasAccepted() {
        return accepted;
    }

    public void setAccepted(boolean b) {
        accepted = b;
    }
    
    public void open(Wandora w, Context c) {
        context = c;
        accepted = false;
        dialog = new JDialog(w, true);
        dialog.setSize(550, 300);
        dialog.add(this);
        dialog.setTitle("Freebase API extractor");
        UIBox.centerWindow(dialog, w);
        dialog.setVisible(true);
    }

    public WandoraTool[] getExtractors(FreebaseExtractor tool) throws TopicMapException {
        Component component = freebaseTabbedPane.getSelectedComponent();
        WandoraTool wt = null;
        ArrayList<WandoraTool> wts = new ArrayList();
        
        try{
            maxDepth = Integer.parseInt(mqlDepthTextField.getText());
            maxExtractCount = Integer.parseInt(mqlMaxCountTextField.getText());
        } catch (NumberFormatException ex) {
            throw new TopicMapException("Invalid depth or topic count!");
        }
        
        
        toggleLimit = mqlToggleCountCheckBox.isSelected();
        
        String[] idarray = new String[0];
        
        if(component.equals(mqlIDQueryPanel)){
            String ids = mqlQueryTextField.getText();
            idarray = ids.split((","));
        } else if (component.equals(mqlSearchQueryPanel)) {
            int[] selectedIndices = searchQueryResultList.getSelectedIndices();
            idarray = new String[selectedIndices.length];
            for (int i = 0; i < selectedIndices.length; i++) {
                idarray[i] = searchListIds.get(i).trim();
            }
        } else {
            try{
                String urlText = urlQueryTextField.getText();
                if ( urlText.indexOf("freebase.com") == -1) throw new MalformedURLException();
                URL url = new URL(urlText);
                String id = url.getPath().replace("/view", "").trim();
                idarray = new String[1];
                idarray[0] = id; 
            } catch (MalformedURLException ex) {
                throw new TopicMapException("Invalid URL!");
            }
        }
        
        ArrayList<String> urls = new ArrayList<String>();
        for ( String id : idarray){
            id = id.trim();
            String query = AbstractFreebaseExtractor.getQuery(id);


            String extractUrl = FREEBASE_MQL_API_BASE +"?query=" + urlEncode(query);

            System.out.println("URL: " + extractUrl);

            urls.add(extractUrl);

        }
        FreebaseMQLExtractor ex = new FreebaseMQLExtractor();
        ex.setForceUrls(urls.toArray(new String[urls.size()-1]));
        wt = ex;
        wts.add(wt);
            
        return wts.toArray(new WandoraTool[]{});
    }
    
    protected static String urlEncode(String str) {
        try {
            str = URLEncoder.encode(str, "utf-8");
        } catch (Exception e) {
        }
        return str;
    }
    
    private void executeFreebaseSearch(String queryText){
        try{
            String urlQuery = "https://www.googleapis.com/freebase/v1/search?query=" + urlEncode(queryText);
            String in;
            URL u = new URL(urlQuery);
            in = IObox.doUrl(u);
            
            JSONObject json = new JSONObject(in);
            JSONArray results = json.getJSONArray("result");
            DefaultListModel model = new DefaultListModel();
            searchQueryResultList.setModel(model);
            searchListIds = new ArrayList<String>();
            
            for( int i = 0; i < results.length(); i++ ){
                JSONObject result = results.getJSONObject(i);
                searchListIds.add(result.getString("mid"));
                String listText = result.getString("name");
                if(result.has(("notable"))){
                   String notable = result.getJSONObject("notable").getString("name");
                   listText += " [" + notable + "]";
                }
                model.add(i, listText);
            }
            
        } catch (IOException e) {
            e.printStackTrace();
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }
    
    public String getContextAsString() {
        StringBuffer sb = new StringBuffer("");
        if(context != null) {
            try {
                Iterator contextObjects = context.getContextObjects();
                String str = null;
                Object o = null;
                while(contextObjects.hasNext()) {
                    str = null;
                    o = contextObjects.next();
                    if(o instanceof Topic) {
                        Topic t = (Topic) o;
                        str = t.getOneSubjectIdentifier().toString();
                        URL url = new URL(str);
                        str = url.getPath();
                        if(str != null) {
                            str = str.trim();
                        }
                    }
                    
                    if(str != null && str.length() > 0) {
                        sb.append(str);
                        if(contextObjects.hasNext()) {
                            sb.append(", ");
                        }
                    }
                }
            }
            catch(Exception e) {
                e.printStackTrace();
            }
        }
        return sb.toString();
    }
    
    
    /*
   * This method is called from within the constructor to initialize the form.
   * WARNING: Do NOT modify this code. The content of this method is always regenerated
   * by the Form Editor.
   */
    
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {
        java.awt.GridBagConstraints gridBagConstraints;

        freebaseMQLQueryPanel = new javax.swing.JPanel();
        freebaseTabbedPane = new SimpleTabbedPane();
        mqlSearchQueryPanel = new javax.swing.JPanel();
        searchQueryLabel = new SimpleLabel();
        searchQueryTextField = new SimpleField();
        searchQueryScrollPane = new javax.swing.JScrollPane();
        searchQueryResultList = new javax.swing.JList();
        searchQuerySubmitButton = new SimpleButton();
        mqlIDQueryPanel = new javax.swing.JPanel();
        mqlQueryLabel = new SimpleLabel();
        mqlQueryTextField = new SimpleField();
        mqlQueryContextButton = new SimpleButton();
        mqlURLQueryPanel = new javax.swing.JPanel();
        urlQueryLabel = new javax.swing.JLabel();
        urlQueryTextField = new javax.swing.JTextField();
        mqlDepthLabel = new SimpleLabel();
        mqlDepthTextField = new SimpleField();
        mqlMaxCountLabel = new SimpleLabel();
        mqlMaxCountTextField = new SimpleField();
        mqlToggleCountCheckBox = new SimpleCheckBox();
        jPanel1 = new javax.swing.JPanel();
        okButton = new SimpleButton();
        cancelButton = new SimpleButton();

        setMinimumSize(new java.awt.Dimension(160, 30));
        setPreferredSize(new java.awt.Dimension(160, 30));
        setLayout(new java.awt.GridBagLayout());

        freebaseMQLQueryPanel.setLayout(new java.awt.GridBagLayout());

        mqlSearchQueryPanel.setLayout(new java.awt.GridBagLayout());

        searchQueryLabel.setText("Free text search");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.insets = new java.awt.Insets(2, 2, 2, 2);
        mqlSearchQueryPanel.add(searchQueryLabel, gridBagConstraints);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.weightx = 0.1;
        gridBagConstraints.insets = new java.awt.Insets(2, 2, 2, 2);
        mqlSearchQueryPanel.add(searchQueryTextField, gridBagConstraints);

        searchQueryScrollPane.setViewportView(searchQueryResultList);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.gridwidth = 3;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 0.1;
        gridBagConstraints.weighty = 0.1;
        gridBagConstraints.insets = new java.awt.Insets(2, 2, 2, 2);
        mqlSearchQueryPanel.add(searchQueryScrollPane, gridBagConstraints);

        searchQuerySubmitButton.setText("Search");
        searchQuerySubmitButton.setMargin(new java.awt.Insets(1, 6, 1, 6));
        searchQuerySubmitButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                searchQuerySubmitButtonActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.insets = new java.awt.Insets(4, 4, 4, 4);
        mqlSearchQueryPanel.add(searchQuerySubmitButton, gridBagConstraints);

        freebaseTabbedPane.addTab("Text search", mqlSearchQueryPanel);

        mqlIDQueryPanel.setLayout(new java.awt.GridBagLayout());

        mqlQueryLabel.setText("Freebase ID");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.FIRST_LINE_START;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(4, 4, 4, 4);
        mqlIDQueryPanel.add(mqlQueryLabel, gridBagConstraints);

        mqlQueryTextField.setText("/en/jane_austen");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.FIRST_LINE_START;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(4, 4, 4, 4);
        mqlIDQueryPanel.add(mqlQueryTextField, gridBagConstraints);

        mqlQueryContextButton.setText("Get context");
        mqlQueryContextButton.setMargin(new java.awt.Insets(1, 6, 1, 6));
        mqlQueryContextButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                mqlQueryContextButtonActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.PAGE_END;
        gridBagConstraints.insets = new java.awt.Insets(4, 4, 4, 4);
        mqlIDQueryPanel.add(mqlQueryContextButton, gridBagConstraints);

        freebaseTabbedPane.addTab("Freebase ID", mqlIDQueryPanel);

        mqlURLQueryPanel.setLayout(new java.awt.GridBagLayout());

        urlQueryLabel.setText("Freebase URL");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.anchor = java.awt.GridBagConstraints.FIRST_LINE_START;
        gridBagConstraints.weightx = 0.1;
        gridBagConstraints.insets = new java.awt.Insets(4, 4, 4, 4);
        mqlURLQueryPanel.add(urlQueryLabel, gridBagConstraints);

        urlQueryTextField.setText("http://www.freebase.com/view/en/jane_austen");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.FIRST_LINE_START;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(4, 4, 4, 4);
        mqlURLQueryPanel.add(urlQueryTextField, gridBagConstraints);

        freebaseTabbedPane.addTab("Freebase URL", mqlURLQueryPanel);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.gridwidth = 8;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 0.1;
        gridBagConstraints.weighty = 1.5;
        freebaseMQLQueryPanel.add(freebaseTabbedPane, gridBagConstraints);

        mqlDepthLabel.setText("Max depth");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.insets = new java.awt.Insets(2, 2, 2, 2);
        freebaseMQLQueryPanel.add(mqlDepthLabel, gridBagConstraints);

        mqlDepthTextField.setHorizontalAlignment(javax.swing.JTextField.CENTER);
        mqlDepthTextField.setText("1");
        mqlDepthTextField.setMaximumSize(new java.awt.Dimension(20, 2147483647));
        mqlDepthTextField.setMinimumSize(new java.awt.Dimension(20, 20));
        mqlDepthTextField.setPreferredSize(new java.awt.Dimension(20, 20));
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.weightx = 0.1;
        gridBagConstraints.insets = new java.awt.Insets(2, 2, 2, 2);
        freebaseMQLQueryPanel.add(mqlDepthTextField, gridBagConstraints);

        mqlMaxCountLabel.setText("Max topic count");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.insets = new java.awt.Insets(2, 2, 2, 2);
        freebaseMQLQueryPanel.add(mqlMaxCountLabel, gridBagConstraints);

        mqlMaxCountTextField.setHorizontalAlignment(javax.swing.JTextField.CENTER);
        mqlMaxCountTextField.setText("1500");
        mqlMaxCountTextField.setMaximumSize(new java.awt.Dimension(40, 2147483647));
        mqlMaxCountTextField.setMinimumSize(new java.awt.Dimension(40, 20));
        mqlMaxCountTextField.setPreferredSize(new java.awt.Dimension(40, 20));
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 3;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.weightx = 0.1;
        gridBagConstraints.insets = new java.awt.Insets(2, 2, 2, 2);
        freebaseMQLQueryPanel.add(mqlMaxCountTextField, gridBagConstraints);

        mqlToggleCountCheckBox.setText("No limit");
        mqlToggleCountCheckBox.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                mqlToggleCountCheckBoxStateChanged(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 4;
        gridBagConstraints.gridy = 1;
        freebaseMQLQueryPanel.add(mqlToggleCountCheckBox, gridBagConstraints);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 5;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.weightx = 1.0;
        freebaseMQLQueryPanel.add(jPanel1, gridBagConstraints);

        okButton.setText("Extract");
        okButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                okButtonActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 6;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.insets = new java.awt.Insets(4, 4, 4, 0);
        freebaseMQLQueryPanel.add(okButton, gridBagConstraints);

        cancelButton.setText("Cancel");
        cancelButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                cancelButtonActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 7;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.insets = new java.awt.Insets(4, 4, 4, 4);
        freebaseMQLQueryPanel.add(cancelButton, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.weighty = 1.0;
        add(freebaseMQLQueryPanel, gridBagConstraints);
    }// </editor-fold>//GEN-END:initComponents

    private void okButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_okButtonActionPerformed
        accepted = true;
        if (this.dialog != null) {
            this.dialog.setVisible(false);
        }
    }//GEN-LAST:event_okButtonActionPerformed

    private void cancelButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cancelButtonActionPerformed
        accepted = false;
        if (this.dialog != null) {
            this.dialog.setVisible(false);
        }
    }//GEN-LAST:event_cancelButtonActionPerformed

    private void mqlToggleCountCheckBoxStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_mqlToggleCountCheckBoxStateChanged
        if (mqlToggleCountCheckBox.isSelected()) mqlMaxCountTextField.setEnabled(false);
        else mqlMaxCountTextField.setEnabled(true);
    }//GEN-LAST:event_mqlToggleCountCheckBoxStateChanged

    private void searchQuerySubmitButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_searchQuerySubmitButtonActionPerformed
        executeFreebaseSearch(searchQueryTextField.getText());
    }//GEN-LAST:event_searchQuerySubmitButtonActionPerformed

    private void mqlQueryContextButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_mqlQueryContextButtonActionPerformed
        mqlQueryTextField.setText(getContextAsString());
    }//GEN-LAST:event_mqlQueryContextButtonActionPerformed

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton cancelButton;
    private javax.swing.JPanel freebaseMQLQueryPanel;
    private javax.swing.JTabbedPane freebaseTabbedPane;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JLabel mqlDepthLabel;
    private javax.swing.JTextField mqlDepthTextField;
    private javax.swing.JPanel mqlIDQueryPanel;
    private javax.swing.JLabel mqlMaxCountLabel;
    private javax.swing.JTextField mqlMaxCountTextField;
    private javax.swing.JButton mqlQueryContextButton;
    private javax.swing.JLabel mqlQueryLabel;
    private javax.swing.JTextField mqlQueryTextField;
    private javax.swing.JPanel mqlSearchQueryPanel;
    private javax.swing.JCheckBox mqlToggleCountCheckBox;
    private javax.swing.JPanel mqlURLQueryPanel;
    private javax.swing.JButton okButton;
    private javax.swing.JLabel searchQueryLabel;
    private javax.swing.JList searchQueryResultList;
    private javax.swing.JScrollPane searchQueryScrollPane;
    private javax.swing.JButton searchQuerySubmitButton;
    private javax.swing.JTextField searchQueryTextField;
    private javax.swing.JLabel urlQueryLabel;
    private javax.swing.JTextField urlQueryTextField;
    // End of variables declaration//GEN-END:variables
}
