package io.jenkins.plugins;

import hudson.EnvVars;
import hudson.Extension;
import hudson.FilePath;
import hudson.Launcher;
import hudson.model.AbstractProject;
import hudson.model.Run;
import hudson.model.TaskListener;
import hudson.tasks.BuildStepDescriptor;
import hudson.tasks.Builder;
import io.jenkins.plugins.enums.BtnLayoutEnum;
import io.jenkins.plugins.enums.MsgTypeEnum;
import io.jenkins.plugins.model.ButtonModel;
import io.jenkins.plugins.model.MessageModel;
import io.jenkins.plugins.service.impl.DingTalkServiceImpl;
import io.jenkins.plugins.tools.Logger;
import io.jenkins.plugins.tools.Utils;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.annotation.Nonnull;
import jenkins.model.Jenkins;
import jenkins.tasks.SimpleBuildStep;
import lombok.Getter;
import lombok.Setter;
import org.apache.commons.lang.StringUtils;
import org.jenkinsci.Symbol;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.DataBoundSetter;

/**
 * 支持 pipeline 中使用
 * <p>
 * * 不要使用 @Data 注解,spotbugs 会报错 * <p> * Redundant nullcheck of this$title, which is known to be
 * non-null in * io.jenkins.plugins.model.MessageModel.equals(Object)
 *
 * @author liuwei
 * @date 2020/3/27 16:36
 */

@Getter
@Setter
@SuppressWarnings("unused")
public class DingTalkPipeline extends Builder implements SimpleBuildStep {

  /**
   * 机器人 id
   */
  private String robot;

  private MsgTypeEnum type;

  private Set<String> at;

  private boolean atAll;

  private String title;

  private List<String> text;

  private String messageUrl;

  private String picUrl;

  private String singleTitle;

  private String singleUrl;

  private List<ButtonModel> btns;

  private BtnLayoutEnum btnLayout;

  private boolean hideAvatar;

  private String rootPath = Jenkins.get().getRootUrl();

  private DingTalkServiceImpl service = new DingTalkServiceImpl();

  @DataBoundConstructor
  public DingTalkPipeline(String robot) {
    this.robot = robot;
  }

  @DataBoundSetter
  public void setType(MsgTypeEnum type) {
    if (type == null) {
      type = MsgTypeEnum.MARKDOWN;
    }
    this.type = type;
  }

  @DataBoundSetter
  public void setAt(List<String> at) {
    if (!(at == null || at.isEmpty())) {
      this.at = new HashSet<>(at);
    }
  }

  @DataBoundSetter
  public void setAtAll(boolean atAll) {
    this.atAll = atAll;
  }

  @DataBoundSetter
  public void setTitle(String title) {
    this.title = title;
  }

  @DataBoundSetter
  public void setText(List<String> text) {
    this.text = text;
  }

  @DataBoundSetter
  public void setMessageUrl(String messageUrl) {
    this.messageUrl = messageUrl;
  }

  @DataBoundSetter
  public void setPicUrl(String picUrl) {
    this.picUrl = picUrl;
  }

  @DataBoundSetter
  public void setSingleTitle(String singleTitle) {
    this.singleTitle = singleTitle;
  }

  @DataBoundSetter
  public void setSingleUrl(String singleUrl) {
    this.singleUrl = singleUrl;
  }

  @DataBoundSetter
  public void setBtns(List<ButtonModel> btns) {
    this.btns = btns;
  }

  @DataBoundSetter
  public void setBtnLayout(BtnLayoutEnum btnLayout) {
    this.btnLayout = btnLayout;
  }

  @DataBoundSetter
  public void setHideAvatar(boolean hideAvatar) {
    this.hideAvatar = hideAvatar;
  }

  /**
   * 获取按钮排列方向
   *
   * @return 水平或则垂直
   */
  public String getBtnLayout() {
    return BtnLayoutEnum.V.equals(btnLayout) ? "0" : "1";
  }

  public String isHideAvatar() {
    return hideAvatar ? "1" : "0";
  }

  @Override
  public void perform(@Nonnull Run<?, ?> run, @Nonnull FilePath workspace,
      @Nonnull Launcher launcher, @Nonnull TaskListener listener)
      throws InterruptedException, IOException {

    EnvVars envVars = run.getEnvironment(listener);

    boolean defaultBtns = MsgTypeEnum.ACTION_CARD.equals(type) &&
        StringUtils.isEmpty(singleTitle) &&
        (btns == null || btns.isEmpty());

    if (defaultBtns) {
      String jobUrl = rootPath + run.getUrl();
      this.btns = Utils.createDefaultBtns(jobUrl);
    } else if (btns != null) {
      btns.forEach(item -> {
        item.setTitle(
            envVars.expand(
                item.getTitle()
            )
        );
        item.setActionUrl(
            envVars.expand(
                item.getActionUrl()
            )
        );
      });
    }

    if (at != null) {
      String atStr = envVars.expand(
          Utils.join(at)
      );

      this.at = new HashSet<>(
          Arrays.asList(
              Utils.split(atStr)
          )
      );
    }

    String result = service.send(
        robot,
        MessageModel.builder()
            .type(type)
            .atMobiles(at)
            .atAll(atAll)
            .title(
                envVars.expand(title)
            )
            .text(
                envVars.expand(
                    Utils.join(text)
                )
            )
            .messageUrl(
                envVars.expand(messageUrl)
            )
            .picUrl(
                envVars.expand(picUrl)
            )
            .singleTitle(
                envVars.expand(singleTitle)
            )
            .singleUrl(
                envVars.expand(singleUrl)
            )
            .btns(btns)
            .btnOrientation(
                getBtnLayout()
            )
            .hideAvatar(isHideAvatar())
            .build()
    );
    if (!StringUtils.isEmpty(result)) {
      Logger.error(listener, result);
    }
  }

  @Symbol({"dingtalk", "dingTalk"})
  @Extension
  public static class DescriptorImpl extends BuildStepDescriptor<Builder> {

    @Nonnull
    @Override
    public String getDisplayName() {
      return "DingTalk";
    }

    @Override
    public boolean isApplicable(Class<? extends AbstractProject> t) {
      return false;
    }
  }
}