/*
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements.  See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License.  You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package rocketmq

import (
	"context"
	"github.com/pkg/errors"

	"github.com/apache/rocketmq-client-go/v2/consumer"
	"github.com/apache/rocketmq-client-go/v2/primitive"
	"github.com/apache/rocketmq-client-go/v2/producer"
)

type Producer interface {
	Start() error
	Shutdown() error
	SendSync(ctx context.Context, mq ...*primitive.Message) (*primitive.SendResult, error)
	SendAsync(ctx context.Context, mq func(ctx context.Context, result *primitive.SendResult, err error),
		msg ...*primitive.Message) error
	SendOneWay(ctx context.Context, mq ...*primitive.Message) error
}

func NewProducer(opts ...producer.Option) (Producer, error) {
	return producer.NewDefaultProducer(opts...)
}

type TransactionProducer interface {
	Start() error
	Shutdown() error
	SendMessageInTransaction(ctx context.Context, mq *primitive.Message) (*primitive.TransactionSendResult, error)
}

func NewTransactionProducer(listener primitive.TransactionListener, opts ...producer.Option) (TransactionProducer, error) {
	return producer.NewTransactionProducer(listener, opts...)
}

type PushConsumer interface {
	// Start the PullConsumer for consuming message
	Start() error

	// Shutdown the PullConsumer, all offset of MessageQueue will be sync to broker before process exit
	Shutdown() error
	// Subscribe a topic for consuming
	Subscribe(topic string, selector consumer.MessageSelector,
		f func(context.Context, ...*primitive.MessageExt) (consumer.ConsumeResult, error)) error

	// Unsubscribe a topic
	Unsubscribe(topic string) error
}

func NewPushConsumer(opts ...consumer.Option) (PushConsumer, error) {
	return consumer.NewPushConsumer(opts...)
}

type PullConsumer interface {
	// Start the PullConsumer for consuming message
	Start() error

	// Shutdown the PullConsumer, all offset of MessageQueue will be commit to broker before process exit
	Shutdown() error

	// Subscribe a topic for consuming
	Subscribe(topic string, selector consumer.MessageSelector) error

	// Unsubscribe a topic
	Unsubscribe(topic string) error

	// MessageQueues get MessageQueue list about for a given topic. This method will issue a remote call to the server
	// if it does not already have any MessageQueue about the given topic.
	MessageQueues(topic string) []primitive.MessageQueue

	// Pull message for the topic specified. It is an error to not have subscribed to any topics before pull for message
	//
	// Specified numbers of messages is returned if message greater that numbers, and the offset will auto forward.
	// It means that if you meeting messages consuming failed, you should process failed messages by yourself.
	Pull(ctx context.Context, topic string, numbers int) (*primitive.PullResult, error)

	// Pull message for the topic specified from a specified MessageQueue and offset. It is an error to not have
	// subscribed to any topics before pull for message. the method will not affect the offset recorded
	//
	// Specified numbers of messages is returned.
	PullFrom(ctx context.Context, mq primitive.MessageQueue, offset int64, numbers int) (*primitive.PullResult, error)

	// Lookup offset for the given message queue by timestamp. The returned offset for the message queue is the
	// earliest offset whose timestamp is greater than or equal to the given timestamp in the corresponding message
	// queue.
	//
	// Timestamp must be millisecond level, if you want to lookup the earliest offset of the mq, you could set the
	// timestamp 0, and if you want to the latest offset the mq, you could set the timestamp math.MaxInt64.
	Lookup(ctx context.Context, mq primitive.MessageQueue, timestamp int64) (int64, error)

	// Commit the offset of specified mqs to broker, if auto-commit is disable, you must commit the offset manually.
	Commit(ctx context.Context, mqs ...primitive.MessageQueue) (int64, error)

	// CommittedOffset return the offset of specified Message
	CommittedOffset(mq primitive.MessageQueue) (int64, error)

	// Seek set offset of the mq, if you wanna re-consuming your message form one position, the method may help you.
	// if you want re-consuming from one time, you cloud Lookup() then seek it.
	Seek(mq primitive.MessageQueue, offset int64) error

	// Pause consuming for specified MessageQueues, after pause, client will not fetch any message from the specified
	// message queues
	//
	// Note that this method does not affect message queue subscription. In particular, it does not cause a group
	// rebalance.
	//
	// if a MessageQueue belong a topic that has not been subscribed, an error will be returned
	//Pause(mqs ...primitive.MessageQueue) error

	// Resume specified message queues which have been paused with Pause, if a MessageQueue that not paused,
	// it will be ignored. if not subscribed, an error will be returned
	//Resume(mqs ...primitive.MessageQueue) error
}

// The PullConsumer has not implemented completely, if you want have an experience of PullConsumer, you could use
// consumer.NewPullConsumer(...), but it may changed in the future.
//
// The PullConsumer will be supported in next release
func NewPullConsumer(opts ...consumer.Option) (PullConsumer, error) {
	return nil, errors.New("pull consumer has not supported")
}
