import enum
import socket

from typing import Optional

class ResponseCode(enum.Enum):
    NNTP_HELP_FOLLOWS                  = 100
    NNTP_CAPABILITIES_FOLLOW           = 101
    NNTP_DATE                          = 111
    NNTP_SERVICE_READY_POST_ALLOWED    = 200
    NNTP_SERVICE_READY_POST_PROHIBITED = 201
    NNTP_CONNECTION_CLOSING            = 205
    NNTP_GROUP_LISTING                 = 211
    NNTP_INFORMATION_FOLLOWS           = 215
    NNTP_ARTICLE_BODY                  = 220
    NNTP_ARTICLE_LISTING               = 221
    NNTP_BODY_LISTING                  = 222
    NNTP_ARTICLE_STAT_RESPONSE         = 223
    NNTP_OVERVIEW_FOLLOWS              = 224
    NNTP_HEADERS_FOLLOW                = 225
    NNTP_ARTICLE_LISTING_ID_FOLLOWS    = 230
    NNTP_GROUPS_NEW_FOLLOW             = 231
    NNTP_ARTICLE_RECEIVED              = 240
    NNTP_AUTH_ACCEPTED                 = 281
    NNTP_INQUIRY_ARTICLE               = 340
    NNTP_INQUIRY_PASSPHRASE            = 381
    NNTP_NEWSGROUP_NOT_FOUND           = 411
    NNTP_NEWSGROUP_NOT_SELECTED        = 412
    NNTP_ARTICLE_INVALID_NUMBER        = 420
    NNTP_ARTICLE_NO_NEXT               = 421
    NNTP_ARTICLE_NO_PREVIOUS           = 422
    NNTP_ARTICLE_NOT_FOUND_NUM         = 423
    NNTP_ARTICLE_NOT_FOUND_ID          = 430
    NNTP_POST_PROHIBITED               = 440
    NNTP_POST_FAILED                   = 441
    NNTP_AUTH_FAILED                   = 481
    NNTP_AUTH_BAD_SEQUENCE             = 482
    NNTP_COMMAND_UNKNOWN               = 500
    NNTP_SYNTAX_ERROR                  = 501
    NNTP_COMMAND_UNAVAILABLE           = 502
    NNTP_GROUPS_UNAVAILABLE            = 503

    def message(self):
        return {
            100: "Help text follows",
            101: "Capabilities follow",
            200: "NNTP Service Ready, posting allowed",
            201: "NNTP Service Ready, posting prohibited",
            205: "Connection closing",
            215: "Information follows",
            223: "Article exists",
            224: "Overview information follows (multi-line)",
            225: "Headers follow (multi-line)",
            231: "List of new newsgroups follows",
            240: "Article received OK",
            281: "Authentication accepted",
            340: "Input article; end with <CR><LF>.<CR><LF>",
            381: "Enter passphrase",
            411: "No such newsgroup",
            412: "No newsgroup selected",
            420: "Current article number is invalid",
            421: "No next article in this group",
            422: "No previous article in this group",
            423: "No article found by that message number",
            430: "No article found by that message ID",
            440: "Posting prohibited",
            441: "Posting failed",
            481: "Authentication failed",
            482: "Authentication commands issued out of sequence",
            500: "Unknown command",
            501: "Syntax error",
            502: "Command unavailable",
            503: "No list of recommended newsgroups available"
        }.get(self.value)

class Response():
    __slots__ = 'code', 'message', 'body',
    
    def __init__(self, code: ResponseCode, message: Optional[str]=None, body: Optional[str]=None):
        self.code    = code
        self.message = message or code.message() or "Unknown response"
        self.body    = body

    def __str__(self):
        ret = "%d %s" % (self.code.value, self.message)

        if self.body:
            ret += "\r\n" + self.body

        return ret