##############################################################################
# ThanCad 0.9.2 "Tartu": n-dimensional CAD with raster support for engineers
#
# Copyright (C) 2001-2026 Thanasis Stamos, January 20, 2026
# Athens, Greece, Europe
# URL: http://thancad.sourceforge.net
# e-mail: cyberthanasis@gmx.net
#
# 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 2 of the License, or
# (at your option) 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 (www.gnu.org/licenses/gpl.html).
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
##############################################################################
"""\
ThanCad 0.9.2 "Tartu": n-dimensional CAD with raster support for engineers

Package which processes commands entered by the user.
This module provides for modification commands of lines.
"""

from math import hypot
from p_gmath import thanNear2
from thandr import ThanLine
from thantrans import T
from thanvar import Canc
from . import thancomsel, thanundo
from .thancommod import thanModEnd, thanModCanc


def thanModMoveLinepoint(proj):
    """Moves a point of a line.

    Note that no selection is made: The selections of 1 point is not recorded.
    """
    retainz = True
    selold = proj[2].thanSelold
    iel = 0
    dodo = []             # Undo/Redo list
    mes1 = T["Select a point of a line to move"]
    dilay = proj[1].thanLayerTree.dilay
    while True:
        opts = []
        if iel > 0: opts.append("undo")
        if len(dodo) > iel: opts.append("redo")
        if len(opts) > 0: mes = "%s (%s): " % (mes1, "/".join(opts))
        else:             mes = "%s: " % mes1
        opts.append("")
        res = thancomsel.thanSelect1Gen(proj, mes, filter=lambda e: isinstance(e, ThanLine), options=opts)
        if res == Canc: break                         # Trim was cancelled/ended
        if res == "": break                           # Trim was cancelled/ended
        if res == "u":
            iel -= 1
            delelems, newelems = dodo[iel]
            proj[1].thanElementDelete(newelems, proj)
            proj[1].thanElementRestore(delelems, proj)
            continue
        if res == "r":
            delelems, newelems = dodo[iel]
            proj[1].thanElementDelete(delelems, proj)
            proj[1].thanElementRestore(newelems, proj)
            iel += 1
            continue
        c1 = proj[2].thanSel1coor
        assert c1 is not None, "thancomsel.thanSelect1Gen does not work well!"
        for elem in proj[2].thanSelall:
            if len(elem.cp) > 0: break    # Get the element
        else:
            continue
        i = min((hypot(c1[0]-cp1[0], c1[1]-cp1[1]), i) for i,cp1 in enumerate(elem.cp))[1]
        stat = T["Move to: "]
        closed = len(elem.cp) > 1 and thanNear2(elem.cp[0], elem.cp[-1])  #Thanasis2025_06_26:hello from Tartu,Estonia
        if closed and (i==0 or i==len(elem.cp)-1):    #Thanasis2025_06_26
            i = 0
            cc = proj[2].thanGudGetLine2(elem.cp[-2], elem.cp[1], stat, statonce="", options=())
        elif i == 0:
            cc = proj[2].thanGudGetLine(elem.cp[1], stat, statonce="", options=())
        elif i == len(elem.cp)-1:
            cc = proj[2].thanGudGetLine(elem.cp[-2], stat, statonce="", options=())  #Here it is guarnteed that at least 2 points are present in the line
        else:
            cc = proj[2].thanGudGetLine2(elem.cp[i-1], elem.cp[i+1], stat, statonce="", options=())
        if cc == Canc: continue

        en = elem.thanClone()
        if retainz: en.cp[i][:2] = cc[:2]
        else:       en.cp[i][:] = cc
        if closed and i==0: en.cp[-1][:] = en.cp[0]  #Thanasis2025_06_26:

        newelems = [en]
        #lay = dilay[elem.thanTags[1]]
        #for e in newelems: proj[1].thanElementTag(e, lay)
        proj[1].thanElementDelete((elem,), proj)
        proj[1].thanElementRestore(newelems, proj)

        proj[2].thanUpdateLayerButton()               # Show current layer again
        del dodo[iel:]
        dodo.append(((elem,), newelems))
        iel += 1

    #proj[2].thanGudSetSelElem(elcut)          # The current selection (cutting edges)
    proj[2].thanGudSetSeloldElem(selold)      # The selection before the command trim started
    if iel == 0: return thanModCanc(proj)     # Trim was cancelled: unselect cutting edges
    delelems = []
    newelems = []
    for i in range(iel):
        delelemsi, newelemsi = dodo[i]
        for e in delelemsi:
            if e in newelems:      #If (e) was a previously new element, then (e) was an intermediate element
                #print e, "is intermediate"
                newelems.remove(e) #which is already deleted, and there is no need to recreate it and redelete it
            else:
                #print e, "is to be deleted"
                delelems.append(e)
        #print newelemsi, "are to be added"
        newelems.extend(newelemsi)
    #print "delelems=", delelems
    #print "newelems=", newelems

    proj[1].thanDoundo.thanAdd("movelinepoint", thanundo.thanReplaceRedo, (delelems, newelems, None),
                                                thanundo.thanReplaceUndo, (delelems, newelems, None))
    thanModEnd(proj)
