// 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 pulsar

import "fmt"

// Result used to represent pulsar processing is an alias of type int.
type Result int

const (
	// ResultOk means no errors
	ResultOk Result = iota
	// ResultUnknownError means unknown error happened on broker
	ResultUnknownError
	// ResultInvalidConfiguration means invalid configuration
	ResultInvalidConfiguration
	// ResultTimeoutError means operation timed out
	ResultTimeoutError
	// ResultLookupError means broker lookup failed
	ResultLookupError
	// ResultInvalidTopicName means invalid topic name
	ResultInvalidTopicName
	// ResultConnectError means failed to connect to broker
	ResultConnectError

	// ReadError means failed to read from socket
	//ReadError                      Result = 6
	// AuthenticationError means authentication failed on broker
	//AuthenticationError            Result = 7
	//AuthorizationError             Result = 8
	//ErrorGettingAuthenticationData Result = 9  // Client cannot find authorization data
	//BrokerMetadataError            Result = 10 // Broker failed in updating metadata
	//BrokerPersistenceError         Result = 11 // Broker failed to persist entry
	//ChecksumError                  Result = 12 // Corrupt message checksum failure
	// ConsumerBusy means Exclusive consumer is already connected
	ConsumerBusy Result = 13
	//NotConnectedError              Result = 14 // Producer/Consumer is not currently connected to broker
	//AlreadyClosedError             Result = 15 // Producer/Consumer is already closed and not accepting any operation
	//InvalidMessage                 Result = 16 // Error in publishing an already used message
	//ConsumerNotInitialized         Result = 17 // Consumer is not initialized
	//ProducerNotInitialized         Result = 18 // Producer is not initialized
	//TooManyLookupRequestException  Result = 19 // Too Many concurrent LookupRequest
	// InvalidUrl means Client Initialized with Invalid Broker Url (VIP Url passed to Client Constructor)
	//InvalidUrl                            Result = 21
	// ServiceUnitNotReady unloaded between client did lookup and producer/consumer got created
	//ServiceUnitNotReady                   Result = 22
	//OperationNotSupported                 Result = 23
	//ProducerBlockedQuotaExceededError     Result = 24 // Producer is blocked
	//ProducerBlockedQuotaExceededException Result = 25 // Producer is getting exception
	//ProducerQueueIsFull                   Result = 26 // Producer queue is full
	//MessageTooBig                         Result = 27 // Trying to send a messages exceeding the max size
	TopicNotFound        Result = 28 // Topic not found
	SubscriptionNotFound Result = 29 // Subscription not found
	//ConsumerNotFound                      Result = 30 // Consumer not found
	// UnsupportedVersionError when an older client/version doesn't support a required feature
	//UnsupportedVersionError               Result = 31
	//TopicTerminated                       Result = 32 // Topic was already terminated
	//CryptoError                           Result = 33 // Error when crypto operation fails
)

// Error implement error interface, composed of two parts: msg and result.
type Error struct {
	msg    string
	result Result
}

func (e *Error) Result() Result {
	return e.result
}

func (e *Error) Error() string {
	return e.msg
}

func newError(result Result, msg string) error {
	return &Error{
		msg:    fmt.Sprintf("%s: %s", msg, getResultStr(result)),
		result: result,
	}
}

func getResultStr(r Result) string {
	switch r {
	case ResultOk:
		return "OK"
	case ResultUnknownError:
		return "Unknown error"
	case ResultInvalidConfiguration:
		return "InvalidConfiguration"
	case ResultTimeoutError:
		return "TimeoutError"
	case ResultLookupError:
		return "LookupError"
	case ResultInvalidTopicName:
		return "InvalidTopicName"
	case ResultConnectError:
		return "ConnectError"
	case ConsumerBusy:
		return "ConsumerBusy"
	default:
		return fmt.Sprintf("Result(%d)", r)
	}
}
