##
# @module    screenshot
# @brief     Screenshot functionality
# @author    Henry Daitx
# @date      Apr 2018
# @copyright Racelogic Ltd., 2018
#

import ft8xx as ft
import gui
import os
import vts

class Screenshot:
    yellow = (32, 32, 0)
    off = (0, 0, 0)

    FT8XX_BUF_ADDR = 0x00080000
    FT8XX_BUF_STRIDE = 40

    progress_leds = (
        yellow + off + off + off,
        yellow + yellow + off + off,
        yellow + yellow + yellow + off,
        yellow + yellow + yellow + yellow,
    )

    bmp_header = bytes((
        0x42, 0x4d, # 'BM'
        0x7a, 0x70, 0x17, 0, # file size: 1536122 bytes
        0, 0, 0, 0, # reserved
        122, 0, 0, 0, # data offset
        108, 0, 0, 0, # DIB header size
        0xe0, 0x01, 0, 0, # width: 480
        0x20, 0x03, 0, 0, # height: 800
        1, 0, # 1 color plane
        32, 0, # 32 bpp
        3, 0, 0, 0, # BI_BITFIELDS, no compression
        0, 0x70, 0x17, 0, # data size: 1536000 bytes
        0x13, 0x0b, 0, 0, 0x13, 0x0b, 0, 0, # 72 DPI
        0, 0, 0, 0, 0, 0, 0, 0, # no palette
        0, 0, 0xff, 0, # R bitmask
        0, 0xff, 0, 0, # G bitmask
        0xff, 0, 0, 0, # B bitmask
        0, 0, 0, 0x00, # A bitmask (we ignore it for displaying, but it's there)
        0x20, 0x6e, 0x69, 0x57, # LCS_WINDOWS_COLOR_SPACE
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    ))

    def get_file_name(self, directory, prefix='screenshot_'):
        directory = directory.rstrip('/')
        try:
            directory_list = os.listdir(directory)
        except OSError:
            return
        directory_list = [
            x for x in directory_list if len(x) == 18 and x[:11] == prefix
        ]
        if not directory_list:
            n = 0
        else:
            n = int(max(directory_list)[11:14]) + 1
        return directory + '/{}{:03}.bmp'.format(prefix, n)

    def set_progress_leds(self, progress):
        vts.leds(*Screenshot.progress_leds[progress & 3])

    def set_progress_leds_off(self):
        vts.leds(*([0] * 12))

    def screenshot(self, addr=FT8XX_BUF_ADDR, stride=FT8XX_BUF_STRIDE):
        if stride & 3:
            raise Exception('stride must be a multiple of 4')

        fn = self.get_file_name('/sd')
        if not fn:
            # No SD card
            return

        gui.pause(True)
        with open(fn, 'wb') as f:
            f.write(Screenshot.bmp_header)
        buf = bytearray(stride * 480 * 4)
        for i in range(800 // stride):
            self.set_progress_leds(4 * i // (800 // stride))
            ft.cpcmd_snapshot2(0x20, addr, 0, i * stride, 960, stride)
            ft.rdbuf(addr, buf)
            with open(fn, 'ab') as f:
                # Circumvent SD write bug ######################################
                pos = 512 - (f.tell() & 511)
                f.write(buf[:pos])
                f.write(buf[pos:])
                ################################################################
        gui.pause(False)
        self.set_progress_leds_off()

# Convenience definition for button callbacks
scrshot_obj = Screenshot()
def screenshot_cb(b):
    scrshot_obj.screenshot()

def screenshot_buf_info():
    return Screenshot.FT8XX_BUF_ADDR,  (Screenshot.FT8XX_BUF_STRIDE * 480 * 4)
