// Copyright 2019 Drone.IO Inc. All rights reserved.
// Use of this source code is governed by the Drone Non-Commercial License
// that can be found in the LICENSE file.

// +build !oss

package validator

import (
	"context"
	"time"

	"github.com/drone/drone-go/drone"
	"github.com/drone/drone-go/plugin/validator"
	"github.com/drone/drone/core"
)

// Remote returns a conversion service that converts the
// configuration file using a remote http service.
func Remote(endpoint, signer string, skipVerify bool, timeout time.Duration) core.ValidateService {
	return &remote{
		endpoint:   endpoint,
		secret:     signer,
		skipVerify: skipVerify,
		timeout:    timeout,
	}
}

type remote struct {
	endpoint   string
	secret     string
	skipVerify bool
	timeout    time.Duration
}

func (g *remote) Validate(ctx context.Context, in *core.ValidateArgs) error {
	if g.endpoint == "" {
		return nil
	}
	// include a timeout to prevent an API call from
	// hanging the build process indefinitely. The
	// external service must return a response within
	// the configured timeout (default 1m).
	ctx, cancel := context.WithTimeout(ctx, g.timeout)
	defer cancel()

	req := &validator.Request{
		Repo:  toRepo(in.Repo),
		Build: toBuild(in.Build),
		Config: drone.Config{
			Data: in.Config.Data,
		},
	}
	client := validator.Client(g.endpoint, g.secret, g.skipVerify)
	err := client.Validate(ctx, req)
	switch err {
	case validator.ErrBlock:
		return core.ErrValidatorBlock
	case validator.ErrSkip:
		return core.ErrValidatorSkip
	default:
		return err
	}
}

func toRepo(from *core.Repository) drone.Repo {
	return drone.Repo{
		ID:         from.ID,
		UID:        from.UID,
		UserID:     from.UserID,
		Namespace:  from.Namespace,
		Name:       from.Name,
		Slug:       from.Slug,
		SCM:        from.SCM,
		HTTPURL:    from.HTTPURL,
		SSHURL:     from.SSHURL,
		Link:       from.Link,
		Branch:     from.Branch,
		Private:    from.Private,
		Visibility: from.Visibility,
		Active:     from.Active,
		Config:     from.Config,
		Trusted:    from.Trusted,
		Protected:  from.Protected,
		Timeout:    from.Timeout,
	}
}

func toBuild(from *core.Build) drone.Build {
	return drone.Build{
		ID:           from.ID,
		RepoID:       from.RepoID,
		Trigger:      from.Trigger,
		Number:       from.Number,
		Parent:       from.Parent,
		Status:       from.Status,
		Error:        from.Error,
		Event:        from.Event,
		Action:       from.Action,
		Link:         from.Link,
		Timestamp:    from.Timestamp,
		Title:        from.Title,
		Message:      from.Message,
		Before:       from.Before,
		After:        from.After,
		Ref:          from.Ref,
		Fork:         from.Fork,
		Source:       from.Source,
		Target:       from.Target,
		Author:       from.Author,
		AuthorName:   from.AuthorName,
		AuthorEmail:  from.AuthorEmail,
		AuthorAvatar: from.AuthorAvatar,
		Sender:       from.Sender,
		Params:       from.Params,
		Deploy:       from.Deploy,
		Started:      from.Started,
		Finished:     from.Finished,
		Created:      from.Created,
		Updated:      from.Updated,
		Version:      from.Version,
	}
}
