// -*- mode: java; c-basic-offset: 2; -*-
// Copyright 2009-2011 Google, All Rights reserved
// Copyright 2011-2020 MIT, All rights reserved
// Released under the Apache License, Version 2.0
// http://www.apache.org/licenses/LICENSE-2.0

package com.google.appinventor.client.wizards;

import static com.google.appinventor.client.Ode.MESSAGES;

import com.allen_sauer.gwt.dnd.client.util.StringUtil;
import com.google.appinventor.client.Ode;
import com.google.appinventor.client.OdeAsyncCallback;
import com.google.appinventor.client.editor.simple.SimpleComponentDatabase;
import com.google.appinventor.client.editor.youngandroid.YaProjectEditor;
import com.google.appinventor.client.explorer.project.Project;
import com.google.appinventor.client.output.OdeLog;
import com.google.appinventor.common.utils.StringUtils;
import com.google.appinventor.client.utils.Uploader;
import com.google.appinventor.shared.rpc.ServerLayout;
import com.google.appinventor.shared.rpc.UploadResponse;
import com.google.appinventor.shared.rpc.component.Component;
import com.google.appinventor.shared.rpc.component.ComponentImportResponse;
import com.google.appinventor.shared.rpc.project.ProjectNode;
import com.google.appinventor.shared.rpc.project.youngandroid.YoungAndroidAssetsFolder;
import com.google.appinventor.shared.rpc.project.youngandroid.YoungAndroidComponentsFolder;
import com.google.appinventor.shared.rpc.project.youngandroid.YoungAndroidProjectNode;

import com.google.gwt.core.client.GWT;
import com.google.gwt.user.cellview.client.CellTable;
import com.google.gwt.user.cellview.client.Column;
import com.google.gwt.user.client.Command;
import com.google.gwt.cell.client.CheckboxCell;
import com.google.gwt.cell.client.NumberCell;
import com.google.gwt.cell.client.TextCell;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.FileUpload;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.TabPanel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.view.client.ListDataProvider;
import com.google.gwt.view.client.SingleSelectionModel;

import java.util.List;

public class ComponentImportWizard extends Wizard {

  final static String external_components = "assets/external_comps/";

  private static class ImportComponentCallback extends OdeAsyncCallback<ComponentImportResponse> {
    @Override
    public void onSuccess(ComponentImportResponse response) {
      if (response.getStatus() == ComponentImportResponse.Status.FAILED){
        Window.alert(MESSAGES.componentImportError() + "\n" + response.getMessage());
        return;
      }
      else if (response.getStatus() != ComponentImportResponse.Status.IMPORTED &&
          response.getStatus() != ComponentImportResponse.Status.UPGRADED) {
        Window.alert(MESSAGES.componentImportError());
        return;
      }
      else if (response.getStatus() == ComponentImportResponse.Status.UNKNOWN_URL) {
        Window.alert(MESSAGES.componentImportUnknownURLError());
      }
      else if (response.getStatus() == ComponentImportResponse.Status.UPGRADED) {
        StringBuilder sb = new StringBuilder(MESSAGES.componentUpgradedAlert());
        for (String name : response.getComponentTypes().values()) {
          sb.append("\n");
          sb.append(name);
        }
        Window.alert(sb.toString());
      }

      List<ProjectNode> compNodes = response.getNodes();
      long destinationProjectId = response.getProjectId();
      long currentProjectId = ode.getCurrentYoungAndroidProjectId();
      if (currentProjectId != destinationProjectId) {
        return; // User switched project early!
      }
      Project project = ode.getProjectManager().getProject(destinationProjectId);
      if (project == null) {
        return; // Project does not exist!
      }
      if (response.getStatus() == ComponentImportResponse.Status.UPGRADED ||
          response.getStatus() == ComponentImportResponse.Status.IMPORTED) {
        YoungAndroidComponentsFolder componentsFolder = ((YoungAndroidProjectNode) project.getRootNode()).getComponentsFolder();
        YaProjectEditor projectEditor = (YaProjectEditor) ode.getEditorManager().getOpenProjectEditor(destinationProjectId);
        if (projectEditor == null) {
          return; // Project is not open!
        }
        for (ProjectNode node : compNodes) {
          project.addNode(componentsFolder, node);
          if ((node.getName().equals("component.json") || node.getName().equals("components.json"))
              && StringUtils.countMatches(node.getFileId(), "/") == 3) {
            projectEditor.addComponent(node, null);
          }
        }
      }
    }
  }

  private static int FROM_MY_COMPUTER_TAB = 0;
  private static int URL_TAB = 1;

  private static final String COMPONENT_ARCHIVE_EXTENSION = ".aix";

  private static final Ode ode = Ode.getInstance();

  public ComponentImportWizard() {
    super(MESSAGES.componentImportWizardCaption(), true, false);

    final CellTable compTable = createCompTable();
    final FileUpload fileUpload = createFileUpload();
    final Grid urlGrid = createUrlGrid();
    final TabPanel tabPanel = new TabPanel();
    tabPanel.add(fileUpload, MESSAGES.componentImportFromComputer());
    tabPanel.add(urlGrid, MESSAGES.componentImportFromURL());
    tabPanel.selectTab(FROM_MY_COMPUTER_TAB);
    tabPanel.addStyleName("ode-Tabpanel");

    VerticalPanel panel = new VerticalPanel();
    panel.add(tabPanel);

    addPage(panel);

    getConfirmButton().setText("Import");

    setPagePanelHeight(150);
    setPixelSize(200, 150);
    setStylePrimaryName("ode-DialogBox");

    initFinishCommand(new Command() {
      @Override
      public void execute() {
        final long projectId = ode.getCurrentYoungAndroidProjectId();
        final Project project = ode.getProjectManager().getProject(projectId);
        final YoungAndroidAssetsFolder assetsFolderNode =
            ((YoungAndroidProjectNode) project.getRootNode()).getAssetsFolder();

        if (tabPanel.getTabBar().getSelectedTab() == URL_TAB) {
          TextBox urlTextBox = (TextBox) urlGrid.getWidget(1, 0);
          String url = urlTextBox.getText();

          if (url.trim().isEmpty()) {
            Window.alert(MESSAGES.noUrlError());
            return;
          }

          ode.getComponentService().importComponentToProject(url, projectId,
              assetsFolderNode.getFileId(), new ImportComponentCallback());
        } else if (tabPanel.getTabBar().getSelectedTab() == FROM_MY_COMPUTER_TAB) {
          if (!fileUpload.getFilename().endsWith(COMPONENT_ARCHIVE_EXTENSION)) {
            Window.alert(MESSAGES.notComponentArchiveError());
            return;
          }

          String url = GWT.getModuleBaseURL() +
            ServerLayout.UPLOAD_SERVLET + "/" +
            ServerLayout.UPLOAD_COMPONENT + "/" +
            trimLeadingPath(fileUpload.getFilename());

          Uploader.getInstance().upload(fileUpload, url,
            new OdeAsyncCallback<UploadResponse>() {
              @Override
              public void onSuccess(UploadResponse uploadResponse) {
                String toImport = uploadResponse.getInfo();
                ode.getComponentService().importComponentToProject(toImport, projectId,
                    assetsFolderNode.getFileId(), new ImportComponentCallback());
              }
            });
          return;
        }
      }

      private String trimLeadingPath(String filename) {
        // Strip leading path off filename.
        // We need to support both Unix ('/') and Windows ('\\') separators.
        return filename.substring(Math.max(filename.lastIndexOf('/'), filename.lastIndexOf('\\')) + 1);
      }
    });
  }

  private CellTable createCompTable() {
    final SingleSelectionModel<Component> selectionModel =
        new SingleSelectionModel<Component>();

    CellTable<Component> compTable = new CellTable<Component>();
    compTable.setSelectionModel(selectionModel);

    Column<Component, Boolean> checkColumn =
        new Column<Component, Boolean>(new CheckboxCell(true, false)) {
          @Override
          public Boolean getValue(Component comp) {
            return selectionModel.isSelected(comp);
          }
        };
    Column<Component, String> nameColumn =
        new Column<Component, String>(new TextCell()) {
          @Override
          public String getValue(Component comp) {
            return comp.getName();
          }
        };
    Column<Component, Number> versionColumn =
        new Column<Component, Number>(new NumberCell()) {
          @Override
          public Number getValue(Component comp) {
            return comp.getVersion();
          }
        };

    compTable.addColumn(checkColumn);
    compTable.addColumn(nameColumn, "Component");
    compTable.addColumn(versionColumn, "Version");

    return compTable;
  }

  private Grid createUrlGrid() {
    TextBox urlTextBox = new TextBox();
    urlTextBox.setWidth("100%");
    Grid grid = new Grid(2, 1);
    grid.setWidget(0, 0, new Label("Url:"));
    grid.setWidget(1, 0, urlTextBox);
    return grid;
  }

  private FileUpload createFileUpload() {
    FileUpload upload = new FileUpload();
    upload.setName(ServerLayout.UPLOAD_COMPONENT_ARCHIVE_FORM_ELEMENT);
    upload.getElement().setAttribute("accept", COMPONENT_ARCHIVE_EXTENSION);
    return upload;
  }

}