#!/usr/bin/env python
# -*- coding: UTF-8 -*-
# vim: expandtab shiftwidth=4
'''
Проект "Построение графика", подзадача pygame 2-1
"Резиновые линии": двухуровневый редизайн
см. диаграммы PyGameState_*.dia
'''

from math import *
import sys

import pygame
pygame.init()
pygame.font.init()

def distance(M1,M2):
    'Расстояние от точки до точки'
    return sqrt(float(M1[0]-M2[0])**2+float(M1[1]-M2[1])**2)

def Draw(screen, pen, width, center, pos, figure):
    if figure == "Line":
        pygame.draw.line(screen, pen, center, pos, width)
    elif figure == "Rect":
        pygame.draw.rect(screen, pen, (center, (pos[0]-center[0],pos[1]-center[1])), width)
    elif figure == "Circle":
        r=int(round(distance(center, pos)))
        pygame.draw.circle(screen, pen, center, max(r, width), width)

def DrawState(screen, event, stages):
    'Рисование фигуры по двум точкам'
    global State, Stage, Center, Copy, pen, width, Action
    if event.type == pygame.MOUSEMOTION:
        if Stage == 2:
            screen.blit(Copy, (0,0))    # восстанавливаем 
            Draw(screen, pen, width, Center, event.pos, Action)
    elif event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
        if Stage == 1:                  # первое нажатие
            Stage = 2
            Center = event.pos
            Copy = screen.copy()        # состояние экрана без нарисованной линии
        elif Stage == stages:           # Последнее нажатие
            Stage = 1
    elif event.type == pygame.MOUSEBUTTONDOWN and event.button == 3:
        if Stage > 1:                   # Нарисовано что-то резиновое
            screen.blit(Copy, (0,0))    # восстанавливаем 
            Stage = 1
    elif event.type == pygame.KEYDOWN and event.key == 27:
        screen.blit(Copy, (0,0))
        State = "Base"

def ScrInput(screen, prompt, pos):
    '''Ввести строку с клавиатуры, отображая её.
    Backspace -- удалить один символ, ESC -- вернуть None'''
    global Copy
    res = ""
    Copy = screen.copy()
    while True:
        text = font.render(prompt+": "+res, 1, (255,255,255))
        screen.blit(Copy, (0,0))
        screen.blit(text, pos)
        pygame.display.flip()
        event = pygame.event.wait()
        if event.type == pygame.KEYDOWN:
            if event.unicode:                     # real characters
                if event.unicode == u"\033":      # ESC
                    res = None
                    break
                elif event.unicode == "\010":     # Backspace
                    res=res[:-1]
                elif event.unicode in u"\r\n":    # Enter
                    break
                elif event.unicode > u" ":        # printable characters
                    res += event.unicode
                #print event.unicode.__repr__()
    screen.blit(Copy, (0,0))
    pygame.display.flip()
    return res

def Ask_n_Do(screen, what, prompt):
    '''Ввести строку, проверить, и сделать с ней что полагается.
    Вернуть True или False в зависимости от успешности'''
    global width, pen
    str_res=ScrInput(screen,u"Введите "+prompt, (10,10))
    if str_res is None: return False    # ввод был прерван
    try:
        res = eval(str_res)
    except:     # неизвестно что, пусть это остаётся строкой
        res = str_res
    if what == "Width":
        if type(res) != int:
            print what, "must be integer"
            return False
        width = res
    elif what == "Color":
        if type(res) not in (list, tuple) or len(res) != 3:
            print what, "must be 3-element list"
            return False
        pen = [r%256 for r in res]      # лень проверять ещё и < 256
    elif what == "Save":
        try:
            pygame.image.save(screen,res)
        except:
            print sys.exc_value
            return False
    elif what == "Edit":
        try:
            newscr = pygame.image.load(res)
            screen.blit(newscr,(0,0))
        except:
            print sys.exc_value
            return False
    return True

# Основной экран
W,H=640,480
screen=pygame.display.set_mode((W,H))

pen,width=(10,100,200),2
font = pygame.font.Font(None, W/24)
States=("Draw", "Input", "Base")
Figures={"o":"Circle", "l":"Line", "r":"Rect"}
Inputs={"w":    ("Width", u"ширину линии"),
        "c":    ("Color", u"цвет линии"),
        "s":    ("Save", u"имя файла для сохранения"),
        "e":    ("Edit", u"имя файла для чтения"),
}
Center=(0,0)
Copy=None

State, Stage, Action = "Base", 1, "Line"
while True:
  pygame.display.flip()
  event = pygame.event.wait()
  # Выход по закрытию окна
  if event.type == pygame.QUIT: sys.exit()
  if State == "Base":   # основное состояние
    if event.type == pygame.KEYDOWN:
        key = event.unicode.lower()
        if key == "q":
            sys.exit()
        elif key in Figures.keys():     # Начать рисование фигуры
            State,Stage,Action = "Draw", 1, Figures[event.unicode.lower()]
            Copy = screen.copy()
        elif key in Inputs.keys():      # Что-то ввести и обработать результат
            Ask_n_Do(screen, *Inputs[key])
  elif State == "Draw": # рисование фигуры
    DrawState(screen, event, 2)
