import sys
import struct
import os

from plesk_mail_migrator.core.dumps.dump_writer import DumpWriter
from plesk_mail_migrator.core.entities.utils.imap_flags_utils import IMAPFlagsUtils
from plesk_mail_migrator.core.entities.utils.mail_message_folder_utils import MailMessageFolderUtils


class StreamDumpWriter(DumpWriter):
    def __init__(self):
        self._stream = sys.stdout
        # On Windows, "\n" is translated into "\r\n" when writing data to stdout,
        # which breaks data stream. To prevent that behavior, switch to binary mode
        # on stdout descriptor in explicit way.
        if sys.platform == "win32":
            import msvcrt
            msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)

    def dump_from_contents(self, message_id, folder, flags, contents):
        """Add mail message to dump. We have message as a string

        :param str|None message_id: Message identifier.
            Check "How the tool works with message IDs" in README for details.
        :param str folder: IMAP folder of the message
        :param IMAPFlags flags: IMAP flags of the message
        :param str contents: String that contains the message
        :rtype: None
        """
        self._write_string(message_id)
        self._write_string(MailMessageFolderUtils.pack_default(folder))
        self._write_int(IMAPFlagsUtils.flags_to_number(flags))
        self._write_string(contents)
        self._stream.flush()

    def _write_int(self, value):
        self._stream.write(struct.pack("=i", value))

    def _write_string(self, value):
        if value is not None:
            self._write_int(len(value))
            self._stream.write(value)
        else:
            self._write_int(0)
