package com.fr.env;

import com.fr.decision.update.data.UpdateConstants;
import com.fr.design.RestartHelper;
import com.fr.design.dialog.FineJOptionPane;
import com.fr.design.gui.ibutton.UIButton;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.i18n.Toolkit;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.layout.TableLayout;
import com.fr.design.layout.TableLayoutHelper;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.update.actions.SyncFileProcess;
import com.fr.design.utils.gui.GUICoreUtils;
import com.fr.design.versioncheck.VersionCheckUtils;
import com.fr.general.CloudCenter;
import com.fr.general.CloudCenterConfig;
import com.fr.general.ComparatorUtils;
import com.fr.general.FRFont;
import com.fr.general.GeneralContext;
import com.fr.general.IOUtils;

import com.fr.general.http.HttpToolbox;
import com.fr.json.JSONArray;
import com.fr.json.JSONObject;
import com.fr.log.FineLoggerFactory;
import com.fr.process.engine.core.FineProcessContext;
import com.fr.process.engine.core.FineProcessEngineEvent;
import com.fr.stable.CommonUtils;
import com.fr.stable.StableUtils;
import com.fr.stable.StringUtils;
import com.fr.stable.project.ProjectConstants;
import com.sun.java.swing.plaf.motif.MotifProgressBarUI;
import java.awt.Color;
import java.awt.Component;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.File;
import java.util.List;
import javax.swing.BorderFactory;
import javax.swing.Icon;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Locale;
import javax.swing.ScrollPaneConstants;
import javax.swing.SwingWorker;
import javax.swing.UIManager;


import static javax.swing.JOptionPane.QUESTION_MESSAGE;

/**
 * @author: Maksim
 * @Date: Created in 2020/2/3
 * @Description: 远程连接时,服务检测提醒对话框
 */
public class CheckServiceDialog extends JDialog implements ActionListener {
    private JPanel topPanel;
    private JPanel centerPanel;
    private UIButton ignoreButton;
    private UIButton syncButton;
    private JProgressBar progressBar;
    private String remoteBuildNo;
    private static final Dimension PROGRESSBAR = new Dimension(120, 15);
    private JSONArray differentPlugins;
    private UILabel affectedFunctionsLabel;
    private UILabel jarCheckResultLabel;
    private UILabel jarCheckTitleLabel;
    private UILabel pluginCheckTitleLabel;

    private JPanel affectedFunctionsDetailsPane;
    private JPanel pluginsCheckResultPanel;
    private JPanel detailsInnerPane;
    private JPanel detailsPane;
    private JScrollPane jScrollPane;
    private Component[][] detailsComponents;
    private Component[][] hideAffectedFunctionsComponents;
    private boolean showAffectedFunctions = true;
    private boolean jarConsistency;
    private double p = TableLayout.PREFERRED;
    private double f = TableLayout.FILL;

    public CheckServiceDialog(Frame parent, String localBranch, String remoteBranch, List<String> noExistServiceDescription) {
        super(parent, true);
        this.remoteBuildNo = remoteBranch;
        this.differentPlugins = VersionCheckUtils.checkLocalAndRemotePlugin();
        this.jarConsistency = ComparatorUtils.equals(localBranch, remoteBranch);
        //上面的标签面板
        topPanel = FRGUIPaneFactory.createBorderLayout_L_Pane();
        JPanel imagePanel = new JPanel();
        Icon icon = IOUtils.readIcon("com/fr/design/images/warnings/warning5.png");

        JLabel imageLabel = new JLabel();
        imageLabel.setIcon(icon);
        imagePanel.add(imageLabel);
        imagePanel.setPreferredSize(new Dimension(110, 100));

        JPanel verticalPanel = FRGUIPaneFactory.createVerticalFlowLayout_S_Pane(true);
        FRFont font = FRFont.getInstance();
        font = font.applySize(15).applyStyle(1);
        UILabel label = new UILabel(Toolkit.i18nText("Fine-Design_Basic_Sync_Branch_Inconsistency"));
        label.setFont(font);
        label.setPreferredSize(new Dimension(650, 30));

        UILabel label2 = new UILabel(Toolkit.i18nText("Fine-Design_Basic_Sync_Inconsistency_Risk"));
        label2.setPreferredSize(new Dimension(600, 30));
        verticalPanel.add(label);
        verticalPanel.add(label2);

        topPanel.add(imagePanel, BorderLayout.WEST);
        topPanel.add(verticalPanel, BorderLayout.CENTER);
        topPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 0, 10));

        //中间的文本域面板
        centerPanel = FRGUIPaneFactory.createBorderLayout_L_Pane();
        centerPanel.setBorder(BorderFactory.createEmptyBorder(0, 10, 10, 10));
        centerPanel.setPreferredSize(new Dimension(480, 320));

        UILabel titleLabel = new UILabel(Toolkit.i18nText("Fine-Design_Basic_Sync_Details"));
        titleLabel.setPreferredSize(new Dimension(400, 40));
        //详情面板
        detailsPane = FRGUIPaneFactory.createY_AXISBoxInnerContainer_L_Pane();
        detailsPane.setBorder(BorderFactory.createEmptyBorder(5, 5, 0, 0));
        detailsPane.setBackground(Color.WHITE);

        jarCheckTitleLabel = new UILabel(Toolkit.i18nText("Fine-Design_Basic_Sync_JAR_Check_title"));
        jarCheckTitleLabel.setBackground(Color.WHITE);


        //插件的检测结果相关面板
        pluginCheckTitleLabel = new UILabel(Toolkit.i18nText("Fine-Design_Basic_Sync_Plugin_Check_title"));
        pluginCheckTitleLabel.setBackground(Color.WHITE);
        initPluginsCheckResultPanel(differentPlugins);

        //jar包检测结果相关面板
        initJarCheckResultPanel(remoteBranch, noExistServiceDescription);

        double[] detailsRowSize;
        double[] detailsColumnSize = {f};

        detailsComponents = new Component[][]{{jarCheckTitleLabel}, {jarCheckResultLabel}, {affectedFunctionsLabel}, {affectedFunctionsDetailsPane}, {pluginCheckTitleLabel}, {pluginsCheckResultPanel}};
        hideAffectedFunctionsComponents = new Component[][]{{jarCheckTitleLabel}, {jarCheckResultLabel}, {affectedFunctionsLabel}, {pluginCheckTitleLabel}, {pluginsCheckResultPanel}};
        if (noExistServiceDescription.size() > 0 && !ComparatorUtils.equals(remoteBranch, localBranch)) {
            detailsRowSize = new double[]{p, p, p, p, p, p};
            detailsInnerPane = TableLayoutHelper.createTableLayoutPane(detailsComponents, detailsRowSize, detailsColumnSize);
        } else {
            detailsRowSize = new double[]{p, p, 0, 0, p, p};
            detailsInnerPane = TableLayoutHelper.createTableLayoutPane(detailsComponents, detailsRowSize, detailsColumnSize);
        }
        detailsInnerPane.setBackground(Color.WHITE);
        jScrollPane = new JScrollPane(detailsInnerPane, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
        jScrollPane.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
        detailsPane.add(jScrollPane);

        centerPanel.add(titleLabel, BorderLayout.NORTH);
        centerPanel.add(detailsPane, BorderLayout.CENTER);
        JPanel buttonPanel = FRGUIPaneFactory.createBorderLayout_M_Pane();
        buttonPanel.setBorder(BorderFactory.createEmptyBorder(0, 10, 10, 10));
        if (isOnline()) {
            ignoreButton = new UIButton(Toolkit.i18nText("Fine-Design_Basic_Sync_Ignore"));
            ignoreButton.addActionListener(this);
            syncButton = new UIButton(Toolkit.i18nText("Fine-Design_Basic_Sync_To_Local"));
            syncButton.setToolTipText(Toolkit.i18nText("Fine-Design_Basic_Sync_To_Local_Tip"));
            syncButton.addMouseListener(syncButtonClickListener);
            progressBar = new JProgressBar();
            progressBar.setUI(new MotifProgressBarUI());
            progressBar.setForeground(UpdateConstants.BAR_COLOR);
            progressBar.setVisible(false);
            progressBar.setStringPainted(true);
            progressBar.setPreferredSize(PROGRESSBAR);
            buttonPanel.add(ignoreButton, BorderLayout.WEST);
            buttonPanel.add(progressBar, BorderLayout.CENTER);
            buttonPanel.add(syncButton, BorderLayout.EAST);
        } else {
            UILabel adviceLabel = new UILabel(Toolkit.i18nText("Fine-Design_Basic_Sync_Suggestion"));
            centerPanel.add(adviceLabel, BorderLayout.SOUTH);
            UIButton okButton = new UIButton(Toolkit.i18nText("Fine-Design_Basic_Remote_Design_Button_Confirm"));
            okButton.addActionListener(this);
            buttonPanel.add(okButton, BorderLayout.EAST);
        }
        this.setTitle(Toolkit.i18nText("Fine-Design_Basic_Remote_Design_Title_Hint"));
        this.setResizable(false);
        this.add(topPanel, BorderLayout.NORTH);
        this.add(centerPanel, BorderLayout.CENTER);
        this.add(buttonPanel, BorderLayout.SOUTH);
        this.setSize(new Dimension(GeneralContext.getLocale().equals(Locale.US) ? 750 : 600, 500));
        GUICoreUtils.centerWindow(this);
    }

    /**
     * 插件检测的结果
     */
    private void initPluginsCheckResultPanel(JSONArray differentPlugins) {

        if (differentPlugins.size() > 0) {
            int size = differentPlugins.size();
            Component[][] pluginCheckResultComponents = new Component[size][1];
            double[] pluginCheckResultColumnSize = new double[size];
            for (int i = 0; i < size; i++) {
                JSONObject plugin = differentPlugins.getJSONObject(i);
                JLabel pluginLabel;
                if (ComparatorUtils.equals(VersionCheckUtils.INCONSISTENCY, plugin.getString("type"))) {
                    pluginLabel = new JLabel("\"" + plugin.getString("name") + "\"" + Toolkit.i18nText("Fine-Design_Basic_Sync_Plugin_Inconsistency_Info") + plugin.getString("version"));
                } else if (ComparatorUtils.equals(VersionCheckUtils.MISSING, plugin.getString("type"))) {
                    pluginLabel = new JLabel("\"" + plugin.getString("name") + "\"" + Toolkit.i18nText("Fine-Design_Basic_Sync_Plugin_Missing_Info") + plugin.getString("version"));
                } else {
                    continue;
                }
                pluginLabel.setIcon(IOUtils.readIcon("com/fr/design/icon/versioncheck/fail.png"));
                pluginCheckResultComponents[i][0] = pluginLabel;
                pluginCheckResultColumnSize[i] = p;
            }
            double[] pluginCheckResultRowSize = {f};
            pluginsCheckResultPanel = TableLayoutHelper.createTableLayoutPane(pluginCheckResultComponents, pluginCheckResultColumnSize, pluginCheckResultRowSize);
        } else {
            UILabel pluginCheckResultLabel = new UILabel(Toolkit.i18nText("Fine-Design_Basic_Sync_Plugin_Consistency"));
            pluginCheckResultLabel.setIcon(IOUtils.readIcon("com/fr/design/icon/versioncheck/success.png"));
            pluginsCheckResultPanel = TableLayoutHelper.createTableLayoutPane(new Component[][]{{pluginCheckResultLabel}}, new double[]{p}, new double[]{f});
        }
        pluginsCheckResultPanel.setBackground(Color.WHITE);
    }

    /**
     * jar包检测的结果
     */
    private void initJarCheckResultPanel(String remoteBranch, List<String> noExistServiceDescription) {
        jarCheckResultLabel = new UILabel();
        jarCheckResultLabel.setBackground(Color.WHITE);
        if (jarConsistency) {
            jarCheckResultLabel.setText(Toolkit.i18nText("Fine-Design_Basic_Sync_JAR_Consistency"));
            jarCheckResultLabel.setIcon(IOUtils.readIcon("com/fr/design/icon/versioncheck/success.png"));
        } else {
            jarCheckResultLabel.setText(Toolkit.i18nText("Fine-Design_Basic_Sync_JAR_Inconsistency_Info") + remoteBranch);
            jarCheckResultLabel.setIcon(IOUtils.readIcon("com/fr/design/icon/versioncheck/fail.png"));
            Component[][] noExistServiceComponents;
            int noExistService = noExistServiceDescription.size();
            if (noExistService > 0) {
                affectedFunctionsLabel = new UILabel(Toolkit.i18nText("Fine-Design_Basic_Remote_Design_Affected_Function"));
                affectedFunctionsLabel.setIcon(UIManager.getIcon("OptionPane.narrow.down"));
                affectedFunctionsLabel.setBackground(Color.WHITE);
                affectedFunctionsLabel.addMouseListener(affectedFunctionsClickListener);
                noExistServiceComponents = new Component[noExistServiceDescription.size()][1];
                double[] noExistServiceColumnSize = new double[noExistService];
                for (int i = 0; i < noExistService; i++) {
                    JLabel noExitServiceLabel = new JLabel("   " + noExistServiceDescription.get(i));
                    noExistServiceComponents[i][0] = noExitServiceLabel;
                    noExistServiceColumnSize[i] = p;
                }
                double[] noExistServiceRowSize = {f};
                affectedFunctionsDetailsPane = TableLayoutHelper.createTableLayoutPane(noExistServiceComponents, noExistServiceColumnSize, noExistServiceRowSize);
                affectedFunctionsDetailsPane.setBackground(Color.WHITE);
            }
        }
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        this.dispose();
    }

    private boolean isOnline() {
        if (CloudCenterConfig.getInstance().isOnline()) {
            String ping = CloudCenter.getInstance().acquireConf("ping", StringUtils.EMPTY);
            if (StringUtils.isNotEmpty(ping)) {
                try {
                    return StringUtils.isEmpty(HttpToolbox.get(ping));
                } catch (Exception e) {
                    FineLoggerFactory.getLogger().error(e.getMessage(), e);
                    return false;
                }
            }
        }
        return false;
    }

    private MouseListener affectedFunctionsClickListener = new MouseAdapter() {
        @Override
        public void mouseClicked(MouseEvent e) {
            if (showAffectedFunctions) {
                showAffectedFunctions = false;
                detailsInnerPane.removeAll();
                affectedFunctionsLabel.setIcon(UIManager.getIcon("OptionPane.narrow.right"));
                TableLayoutHelper.addComponent2ResultPane(hideAffectedFunctionsComponents, new double[]{p, p, p, p, p}, new double[]{f}, detailsInnerPane);
                jScrollPane.validate();
                jScrollPane.repaint();
            } else {
                showAffectedFunctions = true;
                detailsInnerPane.removeAll();
                affectedFunctionsLabel.setIcon(UIManager.getIcon("OptionPane.narrow.down"));
                TableLayoutHelper.addComponent2ResultPane(detailsComponents, new double[]{p, p, p, p, p, p}, new double[]{f}, detailsInnerPane);
                jScrollPane.validate();
                jScrollPane.repaint();
            }
        }
    };

    private MouseListener syncButtonClickListener = new MouseAdapter() {
        @Override
        public void mouseClicked(MouseEvent e) {
            String[] option = {Toolkit.i18nText("Fine-Design_Report_Yes"), Toolkit.i18nText("Fine-Design_Report_No")};
            int a = FineJOptionPane.showOptionDialog(getParent(), Toolkit.i18nText("Fine-Design_Basic_Sync_Info_Information"),
                    Toolkit.i18nText("Fine-Design_Basic_Confirm"), JOptionPane.YES_NO_OPTION, QUESTION_MESSAGE, IOUtils.readIcon("com/fr/design/icon/versioncheck/question.png"), option, 1);
            if (0 == a) {
                //jar包一致的话只更新插件
                progressBar.setVisible(true);
                progressBar.setString(Toolkit.i18nText("Fine-Design_Update_Info_Wait_Message"));
                syncButton.setEnabled(false);
                if (!jarConsistency) {
                    deletePreviousPropertyFile();
                    final String installLib = StableUtils.pathJoin(StableUtils.getInstallHome(), ProjectConstants.LOGS_NAME, UpdateConstants.INSTALL_LIB);
                    final JFrame frame = DesignerContext.getDesignerFrame();
                    final RestartHelper helper = new RestartHelper();
                    FineProcessContext.getParentPipe().fire(FineProcessEngineEvent.DESTROY);
                    SyncFailedPluginsDialog syncFailedPluginsDialog = new SyncFailedPluginsDialog(DesignerContext.getDesignerFrame(),JSONArray.create());
                    new SyncFileProcess(progressBar, remoteBuildNo) {
                        @Override
                        public void onDownloadSuccess() {
                            deleteForDesignerUpdate(installLib);
                            progressBar.setVisible(false);
                            JSONArray syncFailedPlugins = getSyncFailedPlugins();
                            if (syncFailedPlugins.size() > 0) {
                                syncFailedPluginsDialog.showSyncFailedPluginsInfo(syncFailedPlugins);
                                syncFailedPluginsDialog.setVisible(true);
                            }
                            helper.restartForUpdate(frame);
                        }

                        @Override
                        public void onDownloadFailed() {
                            progressBar.setVisible(false);
                            deleteForDesignerUpdate(installLib);
                            ErrorDialog errorDialog = new ErrorDialog(DesignerContext.getDesignerFrame(), Toolkit.i18nText("Fine-Design_Basic_Sync_Fail"));
                            errorDialog.setVisible(true);
                            helper.restartForUpdate(frame);
                        }
                    }.execute();
                } else {
                    //到这边说明主jar是一致的,就只尝试同步插件
                    new SwingWorker<JSONArray, Void>() {

                        @Override
                        protected JSONArray doInBackground() {
                            progressBar.setString(Toolkit.i18nText("Fine-Design_Basic_Sync_Plugins"));
                            progressBar.setValue(0);
                            return VersionCheckUtils.syncPlugins(differentPlugins);
                        }

                        @Override
                        protected void done() {
                            progressBar.setVisible(false);
                            JSONArray syncFailedPlugins = null;
                            try {
                                syncFailedPlugins = get();
                            } catch (Exception ex) {
                                FineLoggerFactory.getLogger().error(ex.getMessage(), ex);
                            }
                            if (syncFailedPlugins != null && syncFailedPlugins.size() > 0) {
                                SyncFailedPluginsDialog syncFailedPluginsDialog = new SyncFailedPluginsDialog(DesignerContext.getDesignerFrame(), syncFailedPlugins);
                                syncFailedPluginsDialog.setVisible(true);
                            } else {
                                FineJOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(),
                                        Toolkit.i18nText("Fine-Design_Basic_Sync_Success"),
                                        Toolkit.i18nText("Fine-Design_Basic_Tool_Tips"),
                                        FineJOptionPane.INFORMATION_MESSAGE);
                            }
                            close();
                        }
                    }.execute();
                }
            }
        }
    };

    private boolean deletePreviousPropertyFile() {
        File moveFile = new File(RestartHelper.MOVE_FILE);
        File delFile = new File(RestartHelper.RECORD_FILE);
        if (StableUtils.mkdirs(moveFile) && StableUtils.mkdirs(delFile)) {
            return StableUtils.deleteFile(moveFile) && StableUtils.deleteFile(delFile);
        }
        return false;
    }

    private void close() {
        this.dispose();
    }

    private void deleteForDesignerUpdate(String installLib) {
        File dir = new File(installLib);
        CommonUtils.deleteFile(dir);
    }
}