#!python
#
# Command-driven drawing/visualization/animation/presentation tool.
# Copyright (c) 2018-2023, Hiroyuki Ohsaki.
# All rights reserved.
#

# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# any later version.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <https://www.gnu.org/licenses/>.

# Macro expansion support is contributed by Hal.

import fileinput
import subprocess
import sys
import threading

from perlcompat import die, getopts
import cellx

def usage():
    die(f"""\
usage: {sys.argv[0]} [-dEg] [-c #] [-M class] [-F rate] [-L rate] [-A alpha] [file...]
  -d        debug mode
  -E        enable macro expansion with cpp
  -g        use OpenGL monitor class
  -c #      select color scheme
  -M class  monitor class (Null/SDL/SDL_Filter/PostScript/OpenGL) (default: SDL)
  -F rate   the number of frames per animation/fading
  -L rate   limit the frame rate (default: 60)
  -A alpha  alpha for filtering effect (default: 128)

cellx commands:
{cellx.Parser().help()}""")

def read_via_cpp(parser):
    # Filter all input lines via pre-processor.
    # NOTE: Filter process is invoked as a subprocess, and a thread is created
    # to continuously read output from the subprocess.
    filter = subprocess.Popen(['cpp'],
                              stdin=subprocess.PIPE,
                              stdout=subprocess.PIPE)

    def reader():
        for line in filter.stdout:
            line = line.decode().rstrip()
            parser.parse_line(line)

    th = threading.Thread(target=reader)
    th.start()
    for line in fileinput.input():
        filter.stdin.write(line.encode())
    filter.stdin.close()
    # Wait until the thread is terminated.
    th.join()

def main():
    opt = getopts('dEfgc:M:F:L:A:') or usage()
    debug = opt.d
    enable_cpp = opt.E
    full_screen = opt.f
    enable_opengl = opt.g
    color_scheme = int(opt.c) if opt.c else 0
    frame_rate = float(opt.F) if opt.F else 30
    rate_limit = float(opt.L) if opt.L else 60
    alpha = int(opt.A) if opt.A else 128

    # Identify monitor class.
    monitor_class = 'SDL'
    if enable_opengl:
        monitor_class = 'OpenGL'
    if opt.M:
        monitor_class = opt.M
    # Determine screen resolution.
    width, height = 800, 600
    if full_screen:
        width, height = 1920, 1080

    # Create monitor object.
    cls = eval('cellx.monitor.' + monitor_class)
    mon = cls(width=width,
              height=height,
              alpha=alpha,
              color_scheme=color_scheme)
    # Create cellx and its parser objects.
    cel = cellx.Cell(width=width,
                     height=height,
                     monitor=mon,
                     frame_rate=frame_rate,
                     rate_limit=rate_limit)
    parser = cellx.Parser(cell=cel)

    if enable_cpp:
        read_via_cpp(parser)
    else:
        lineno = 1
        for line in fileinput.input():
            line = line.rstrip()
            if debug:
                print(f'{lineno}: {line}', file=sys.stderr)
            parser.parse_line(line)
            lineno += 1

if __name__ == "__main__":
    main()
