/*
 * 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 "fmt"

func Version() (version string) {
	return GetVersion()
}

// NewProducer create a new producer with config
func NewProducer(config *ProducerConfig) Producer {
	return newDefaultProducer(config)
}

// ProducerConfig define a producer
type ProducerConfig struct {
	GroupID     string
	NameServer  string
	Credentials *SessionCredentials
}

func (config *ProducerConfig) String() string {
	// For security, don't print Credentials default.
	return fmt.Sprintf("[groupId: %s, nameServer: %s]", config.NameServer, config.GroupID)
}

type Producer interface {
	baseAPI
	// SendMessageSync send a message with sync
	SendMessageSync(msg *Message) SendResult

	// SendMessageOrderly send the message orderly
	SendMessageOrderly(msg *Message, selector MessageQueueSelector, arg interface{}, autoRetryTimes int) SendResult

	// SendMessageAsync send a message with async
	SendMessageAsync(msg *Message)
}

// NewPushConsumer create a new consumer with config.
func NewPushConsumer(config *ConsumerConfig) (PushConsumer, error) {
	return newPushConsumer(config)
}

// ConsumerConfig define a new consumer.
type ConsumerConfig struct {
	GroupID             string
	NameServer          string
	ConsumerThreadCount int
	MessageBatchMaxSize int
	//ConsumerInstanceName int
	Credentials *SessionCredentials
}

func (config *ConsumerConfig) String() string {
	return fmt.Sprintf("[groupId: %s, nameServer: %s, consumerThreadCount: %d, messageBatchMaxSize: %d]",
		config.GroupID, config.NameServer, config.ConsumerThreadCount, config.MessageBatchMaxSize)
}

type PushConsumer interface {
	baseAPI
	// Subscribe a new topic with specify filter expression and consume function.
	Subscribe(topic, expression string, consumeFunc func(msg *MessageExt) ConsumeStatus) error
}

type SessionCredentials struct {
	AccessKey string
	SecretKey string
	Channel   string
}

func (session *SessionCredentials) String() string {
	return fmt.Sprintf("[accessKey: %s, secretKey: %s, channel: %s]",
		session.AccessKey, session.SecretKey, session.Channel)
}

type SendResult struct {
	Status SendStatus
	MsgId  string
	Offset int64
}

func (result SendResult) String() string {
	return fmt.Sprintf("[status: %s, messageId: %s, offset: %d]", result.Status, result.MsgId, result.Offset)

}

type baseAPI interface {
	Start() error
	Shutdown() error
}
