#!/usr/bin/env python
# coding: utf-8

"""
Mandatory docstring
"""

# TODO
#
# First and foremost, get rid of duplicate code, i.e. learn to use functions.

from optparse import OptionParser
from random import randrange
import sys, re

SCRIPT_NAME = "cliching"
SCRIPT_VERSION = "1.1.0"

desc = """%prog generates I Ching hexagram (and its relating figure if needed).
    Randomization uses the marble method by default. For the coin method, see
    below.
    """

parser = OptionParser(description=desc)
parser.add_option("-c", "--coin",
        action="store_true",
        default=False,
        dest="coin",
        help="Use the traditional coin method instead of marble picking.")
parser.add_option("-v", "--verbose",
        action="store_true",
        default=False,
        dest="verbose",
        help="Show description(s) as well.")
parser.add_option("-s", "--show",
        metavar="NUMBER",
        type="int",
        dest="hxgrm",
        help="Show certain hexagram (1-64).")
parser.add_option("-f", "--find",
        metavar="STRING",
        dest="hxgrm_str",
        help="Find hexagram by its shape (Use string of 6 numbers [zeros and/or ones] like 001100 where 1 denotes a yang line and 0 yin, from top to bottom).")
parser.add_option("-V", "--version",
        action="store_true",
        default=False,
        dest="version",
        help="Print version number and exit.")

(options, args) = parser.parse_args()

SHAPES =  { 1 : [ "young_yang", "young_yang",  "young_yang",  "young_yang", "young_yang",  "young_yang",  " Force", \
                      "Strength, creative energy, action; the power of heaven to\ncreate and destroy; dynamic, untiring, tenacious, enduring." ],
            2 : [ "young_yin", "young_yin", "young_yin", "young_yin", "young_yin", "young_yin", " Field", \
                      "Yield, nourish, provide; the power to give form to\nall things; receptive, gentle, giving, supple;\nwelcome, consent." ],
            3 : [ "young_yang", "young_yin",  "young_yin",  "young_yin", "young_yang", "young_yin",  "Sprouting", \
                      "Beginning of growth and its problems; gather your\nstrength; establish, found, assemble." ],
            4 : [ "young_yin",  "young_yang", "young_yin",  "young_yin", "young_yin",  "young_yang", "Enveloping", \
                      "Immature, young, unaware; concealed, hidden;\nnurture hidden growth, apprenticeship." ],
            5 : [ "young_yang", "young_yang", "young_yang", "young_yin", "young_yang", "young_yin",  "Attending", \
                      "Wait for, wait on; attend to what is needed; watch\nfor the right moment; participant in a sacrifice." ],
            6 : [ "young_yin",  "young_yang", "young_yin",  "young_yang", "young_yang", "young_yang", "Arguing", \
                      "Dispute, controversy, argument; express your position;\nresolve or retreat from conflict." ],
            7 : [ "young_yin",  "young_yang", "young_yin",  "young_yin", "young_yin",  "young_yin",  "Legions", \
                      "Discipline, organize into functional units, mobilize,\nlead; master of arms." ],
            8 : [ "young_yin",  "young_yin",  "young_yin",  "young_yin", "young_yang", "young_yin",  "Grouping", \
                      "Alliance, mutual support, spiritual kin; how you group\nthings and people; changing groups." ],
            9 : [ "young_yang", "young_yang", "young_yang", "young_yin", "young_yang", "young_yang", "Small\n  Accumulating", \
                      "Accumulate small things to do something great; adapt to each\nthing that crosses your path; nurture, tame, support, collect." ],
            10: [ "young_yang", "young_yang", "young_yin",  "young_yang", "young_yang", "young_yang", "Treading", \
                        "Find and make your way, step by step; conduct, manners,\nsalary, support." ],
            11: [ "young_yang", "young_yang", "young_yang", "young_yin", "young_yin",  "young_yin",  "Pervading", \
                        "Prospering, expanding, great abundance and harmony;\npeace, communication; spring, flowering." ],
            12: [ "young_yin",  "young_yin",  "young_yin",  "young_yang", "young_yang", "young_yang", "Obstruction", \
                        "Obstacle, blocked communication; decline, cut off, closed;\nlate autumn." ],
            13: [ "young_yang", "young_yin",  "young_yang", "young_yang", "young_yang", "young_yang", "Concording\n  People", \
                        "Harmony, bring people together, share your idea or goal,\nwelcome others, co-operate." ],
            14: [ "young_yang", "young_yang", "young_yang", "young_yang", "young_yin",  "young_yang", "  Great\n  Possessions", \
                        "A powerful idea; great power to realize things; organize\nyour efforts, concentrate; great results and achievements." ],
            15: [ "young_yin",  "young_yin",  "young_yang", "young_yin", "young_yin",  "young_yin",  "Humbling", \
                        "Cut through pride and complications, keep close to fundamental\nthings; be simple; think and speak of yourself humbly." ],
            16: [ "young_yin",  "young_yin",  "young_yin",  "young_yang", "young_yin",  "young_yin",  "Providing\n    For", \
                        "Gather what you need to meet the future; able to respond\nimmediately; enjoy, pleasure, enthusiasm, be carried away." ],
            17: [ "young_yang", "young_yin",  "young_yin",  "young_yang", "young_yang", "young_yin",  "Following", \
                        "Be drawn into motion; influenced by, accept guidance;\nmove with the flow, natural and correct." ],
            18: [ "young_yin",  "young_yang", "young_yang", "young_yin", "young_yin",  "young_yang", "Corruption", \
                        "Disorder, perversion or decay with roots in the past,\nblack magic; renew, renovate, find a new beginning." ],
            19: [ "young_yang", "young_yang", "young_yin",  "young_yin", "young_yin",  "young_yin",  "Nearing", \
                        "Approach, the arrival of the new, growing; an honoured\nand powerful force comes nearer." ],
            20: [ "young_yin",  "young_yin",  "young_yin",  "young_yin", "young_yang", "young_yang", "Viewing", \
                        "Look at things from a distance, contemplate, let everything\ncome into view, divine the meaning." ],
            21: [ "young_yang", "young_yin",  "young_yin",  "young_yang", "young_yin",  "young_yang", "Gnawing and\n  Biting Through", \
                        "Confront the problem, bite through the obstacle, be\ntenacious, reveal the essential." ],
            22: [ "young_yang", "young_yin",  "young_yang", "young_yin", "young_yin",  "young_yang", "Adorning", \
                        "Make outward appearance reflect inner worth; embellish,\nbeautify, display courage and beauty to build inner value." ],
            23: [ "young_yin",  "young_yin",  "young_yin",  "young_yin", "young_yin",  "young_yang", "Stripping", \
                        "Strip away old ideas and habits, eliminate what is unusable,\noutmoded or worn out." ],
            24: [ "young_yang", "young_yin",  "young_yin",  "young_yin", "young_yin",  "young_yin",  "Returning", \
                        "Energy and spirit return after a difficult time; renewal,\nre-birth, re-establish; new hope." ],
            25: [ "young_yang", "young_yin",  "young_yin",  "young_yang", "young_yang", "young_yang", "  Without\n  Embroiling", \
                        "Disentangle yourself; spontaneous, unplanned, direct;\nclean, pure, free from confusion or ulterior motives." ],
            26: [ "young_yang", "young_yang", "young_yang", "young_yin", "young_yin",  "young_yang", "  Great\n  Accumulating", \
                        "Concentrate, focus on a great idea; accumulate energy, bring\neverything together; a time for great effort and achievement." ],
            27: [ "young_yang", "young_yin",  "young_yin",  "young_yin", "young_yin",  "young_yang", "  Jaws", \
                        "Nourishing and being nourished, food and words; the mouth,\nyour daily bread; take things in, swallow." ],
            28: [ "young_yin",  "young_yang", "young_yang", "young_yang", "young_yang", "young_yin",  "  Great\n  Exceeding", \
                        "A crisis; gather all your force, don't be afraid to act alone;\nhold on to your ideals." ],
            29: [ "young_yin",  "young_yang", "young_yin",  "young_yin", "young_yang", "young_yin",  "Repeating the\n Gorge", \
                        "Unavoidable danger; take the plunge, face your fear;\npractise, confront something repeatedly." ],
            30: [ "young_yang", "young_yin",  "young_yang", "young_yang", "young_yin",  "young_yang", "Radiance", \
                        "Light, warmth and spreading awareness; join with, adhere to;\nsee clearly." ],
            31: [ "young_yin",  "young_yin",  "young_yang", "young_yang", "young_yang", "young_yin",  "Conjoining", \
                        "Influence or stimulus to action, excite, mobilize; connection,\nbring together what belongs together." ],
            32: [ "young_yin",  "young_yang", "young_yang", "young_yang", "young_yin",  "young_yin",  "Persevering", \
                        "Continue on, endure and renew the way, constant, consistent,\ncontinue in what is right." ],
            33: [ "young_yin",  "young_yin",  "young_yang", "young_yang", "young_yang", "young_yang", "Retiring", \
                        "Withdraw, conceal yourself, retreat; pull back in order to\nadvance later." ],
            34: [ "young_yang", "young_yang", "young_yang", "young_yang", "young_yin",  "young_yin",  "  Great\n  Invigorating", \
                        "Great strength, the strength of the Great, have a firm purpose,\nfocus your strength and go forward." ],
            35: [ "young_yin",  "young_yin",  "young_yin",  "young_yang", "young_yin",  "young_yang", "Prospering", \
                        "Step into the light, advance surely, receive gifts, be promoted,\nspread prosperity, dawn of a new day." ],
            36: [ "young_yang", "young_yin",  "young_yang", "young_yin", "young_yin",  "young_yin",  "  Hiding\n  Brightness", \
                        "Hide your light, protect yourself, accept the difficult task." ],
            37: [ "young_yang", "young_yin",  "young_yang", "young_yin", "young_yang", "young_yang", "  Dwelling\n  People", \
                        "Hold together, an enduring group; adapt, nourish, support;\nfamily, clan." ],
            38: [ "young_yang", "young_yang", "young_yin",  "young_yang", "young_yin",  "young_yang", "Diverging", \
                        "Opposition, discord; change conflict into creative tension\nthrough awareness." ],
            39: [ "young_yin",  "young_yin",  "young_yang", "young_yin", "young_yang", "young_yin",  "Difficulties", \
                        "Confront obstacles; feel hampered or afflicted." ],
            40: [ "young_yin",  "young_yang", "young_yin",  "young_yang", "young_yin",  "young_yin",  "Loosening", \
                        "Solve problems, untie knots, release blocked energy;\nliberation, end of suffering." ],
            41: [ "young_yang", "young_yang", "young_yin",  "young_yin", "young_yin",  "young_yang", "Diminishing", \
                        "Loss, decrease, sacrifice; concentrate, diminish involvements;\naim at a higher goal." ],
            42: [ "young_yang", "young_yin",  "young_yin",  "young_yin", "young_yang", "young_yang", "Augmenting", \
                        "Increase, expand, develop, pour in more, a fertile and\nexpansive time." ],
            43: [ "young_yang", "young_yang", "young_yang", "young_yang", "young_yang", "young_yin",  "Deciding", \
                        "A critical moment, a breakthrough; decide and act clearly,\nclean it out and bring it to light." ],
            44: [ "young_yin",  "young_yang", "young_yang", "young_yang", "young_yang", "young_yang", "Coupling", \
                        "Opening, welcoming, an intense personal encounter; meet and\nact through the yin, sexual intercourse." ],
            45: [ "young_yin",  "young_yin",  "young_yin",  "young_yang", "young_yang", "young_yin",  "Clustering", \
                        "Gather, assemble, collect, bunch together, crowds; a great\neffort brings great rewards." ],
            46: [ "young_yin",  "young_yang", "young_yang", "young_yin", "young_yin",  "young_yin",  "Ascending", \
                        "Rise to a higher level, lift yourself, advance; climb up\nstep by step." ],
            47: [ "young_yin",  "young_yang", "young_yin",  "young_yang", "young_yang", "young_yin",  "Confining", \
                        "Oppression, restriction, being cut off; the moment of truth;\nturn inward, find a way to open communication." ],
            48: [ "young_yin",  "young_yang", "young_yang", "young_yin", "young_yang", "young_yin",  " The Well", \
                        "Communicate, interact, in good order; the underlying structure,\nnetwork; source of life-water necessary to all." ],
            49: [ "young_yang", "young_yin",  "young_yang", "young_yang", "young_yang", "young_yin",  "Skinning", \
                        "Renew; moult, change radically, strip away the old, revolution,\nrevolt." ],
            50: [ "young_yin",  "young_yang", "young_yang", "young_yang", "young_yin",  "young_yang", "The Vessel", \
                        "Transformation, reach to the spiritual level; found, consecrate,\nimagine, contain." ],
            51: [ "young_yang", "young_yin",  "young_yin",  "young_yang", "young_yin",  "young_yin",  " Shake", \
                        "A disturbing and fertilizing shock; wake up, stir up, begin\nthe new; return of life and love in spring." ],
            52: [ "young_yin",  "young_yin",  "young_yang", "young_yin", "young_yin",  "young_yang", " Bound", \
                        "Calm, still, stabilize; limit or boundary, end of a cycle;\nbecome an individual." ],
            53: [ "young_yin",  "young_yin",  "young_yang", "young_yin", "young_yang", "young_yang", "  Gradual\n  Advancing", \
                        "Step by step, smooth, adaptable, penetrate like water;\nthe oldest daughter's marriage." ],
            54: [ "young_yang", "young_yang", "young_yin",  "young_yang", "young_yin",  "young_yin",  "  Converting\n  the Maiden", \
                        "Choice or transformation over which you have no control;\nrealize your hidden potential; passion, desire, irregular progress;\nthe younger daughter's marriage." ],
            55: [ "young_yang", "young_yin",  "young_yang", "young_yang", "young_yin",  "young_yin",  "Abounding", \
                        "Culmination, plenty, copious, profusion; generosity, opulence,\nfull to overflowing." ],
            56: [ "young_yin",  "young_yin",  "young_yang", "young_yang", "young_yin",  "young_yang", "Sojourning", \
                        "Wandering, living in exile, searching for your individual truth;\noutside the social net, on a quest." ],
            57: [ "young_yin",  "young_yang", "young_yang", "young_yin", "young_yang", "young_yang", "  Gently\n  Penetrating", \
                        "Supple, flexible, subtle penetration; accept, let yourself be\nshaped by the situation; support or nourish from below." ],
            58: [ "young_yang", "young_yang", "young_yin",  "young_yang", "young_yang", "young_yin",  " Open", \
                        "Communication, self-expression; pleasure, joy, interaction;\npersuade, exchange, the marketplace." ],
            59: [ "young_yin",  "young_yang", "young_yin",  "young_yin", "young_yang", "young_yang", "Dispersing", \
                        "Dissolve, clear away, scatter, clear up; make fluid, eliminate\nobstacles and misundestandings." ],
            60: [ "young_yang", "young_yang", "young_yin",  "young_yin", "young_yang", "young_yin",  "Articulating", \
                        "Give measure, limit and form; articulate thought and speech;\nrhythm, interval, chapter, units." ],
            61: [ "young_yang", "young_yang", "young_yin",  "young_yin", "young_yang", "young_yang", "  Connecting\n  to Centre", \
                        "Connection to the spirit; just, sincere, truthful; the power of\na heart free of prejudice; connect the inner and outer parts\nof your life." ],
            62: [ "young_yin",  "young_yin",  "young_yang", "young_yang", "young_yin",  "young_yin",  "  Small\n  Exceeding", \
                        "A time of transition, adapt to each different thing; be very\ncareful, very small; excess yin." ],
            63: [ "young_yang", "young_yin",  "young_yang", "young_yin", "young_yang", "young_yin",  "Already\n  Fording", \
                        "Already underway, the action has begun; proceed actively,\neverything is in place and in order." ],
            64: [ "young_yin",  "young_yang", "young_yin",  "young_yang", "young_yin",  "young_yang", "Not Yet\n  Fording", \
                        "On the edge of an important change; gather your energy,\neverything is possible; wait for the right moment." ] }

def special_match(strg, search=re.compile(r'[^01]').search):
    return not bool(search(strg))

def show_hexagram(hxgrm):
    """ Just print chosen hexagram."""

    try:
        hxgrm = int(hxgrm)
    except ValueError:
        print "Invalid format:", hxgrm
        print "Choose an integer between 1 and 64"
        sys.exit(1)

    if (hxgrm < 1) or (hxgrm > 64):
        print "Invalid value:", hxgrm
        print "Choose a value between 1 and 64"
        sys.exit(1)

    i = 5
    while i >= 0:
        if SHAPES[hxgrm][i] == "young_yang":
            print "  ---------"
        elif SHAPES[hxgrm][i] == "young_yin":
            print "  ---   ---"

        i = i - 1
    print
    print "     ", hxgrm
    print " ", SHAPES[hxgrm][6]
    if options.verbose:
        print "\n", SHAPES[hxgrm][7]
    print

    return

def find_hexagram(hxgrm_str):
    """ Find the number of hexagram."""

    hexagram = [ "", "", "", "", "", "" ]
    hexag = str(hxgrm_str);

    if (special_match(hexag) == False):
        print "Invalid string:", hexag
        print "Use only 1's and/or 0's."
        sys.exit(1)

    if (len(hexag) != 6):
        print "Invalid number of characters:", hexag
        print "Only six characters allowed."
        sys.exit(1)

    x = 5
    y = 0
    while x >= 0:
        if hexag[y] == "1":
            hexagram[x] = "young_yang"
            print "  ---------"
        else:
            hexagram[x] = "young_yin"
            print "  ---   ---"
        x = x - 1
        y = y + 1

    right = 0
    i, j, k = 1, 0, 0

    if options.verbose == False:
        while right < 7:
            if SHAPES[i][k] == hexagram[j]:
                right = right + 1
                k = k + 1
                j = j + 1

                if k > 5:
                    print "     ", i
                    print " ", SHAPES[i][6]
                    break
            else:
                right = 0
                i = i + 1
                j, k = 0, 0
    else:
        while right < 7:
            if SHAPES[i][k] == hexagram[j]:
                right = right + 1
                k = k + 1
                j = j + 1

                if k > 5:
                    print "     ", i
                    print " ", SHAPES[i][6]
                    print "\n", SHAPES[i][7]
                    break
            else:
                right = 0
                i = i + 1
                j, k = 0, 0
    print
    return

def main():
    """ Do most of the stuff here """

    marbles = [ "old_yin", "old_yang", "old_yang", "old_yang",
                "young_yang", "young_yang", "young_yang", "young_yang", "young_yang",
                "young_yin", "young_yin", "young_yin", "young_yin", "young_yin",
                "young_yin", "young_yin" ]
    hexagram = [ "", "", "", "", "", "" ]
    primary_shape = [ "", "", "", "", "", "" ]
    relating_shape = [ "", "", "", "", "", "" ]

    relating = False

    if options.version:
        print SCRIPT_NAME, SCRIPT_VERSION
        sys.exit()

    if options.hxgrm:
        show_hexagram(options.hxgrm)
        sys.exit()

    if options.hxgrm_str:
        find_hexagram(options.hxgrm_str)
        sys.exit()

    # Randomize primary hexagram
    if options.coin == True:

        loop = 0
        print "Tossed coins.\n"
        while loop < 6:
            coin1 = randrange(2, 4)
            coin2 = randrange(2, 4)
            coin3 = randrange(2, 4)
            total = coin1 + coin2 + coin3

            if total == 6:
                hexagram[loop] = "old_yin"
            elif total == 9:
                hexagram[loop] = "old_yang"
            elif total == 7:
                hexagram[loop] = "young_yang"
            else:
                hexagram[loop] = "young_yin"

            loop = loop + 1
    else:
        loop = 0
        while loop < 6:
            line = randrange(0, len(marbles))

            hexagram[loop] = marbles[line]
            loop = loop + 1

    # Make simplified shapes for easier parsing
    i = 0
    while i < len(hexagram):
        if hexagram[i] == "old_yin":
            primary_shape[i] = "young_yin"
            relating_shape[i] = "young_yang"
        elif hexagram[i] == "old_yang":
            primary_shape[i] = "young_yang"
            relating_shape[i] = "young_yin"
        elif hexagram[i] == "young_yang":
            primary_shape[i] = "young_yang"
            relating_shape[i] = "young_yang"
        elif hexagram[i] == "young_yin":
            primary_shape[i] = "young_yin"
            relating_shape[i] = "young_yin"

        i = i + 1

    print "Primary Figure"

    i = 5
    while i >= 0:
        if hexagram[i] == "old_yin":
            relating = True
            print "  --- x ---"
        elif hexagram[i] == "old_yang":
            relating = True
            print "  ----O----"
        elif hexagram[i] == "young_yang":
            print "  ---------"
        elif hexagram[i] == "young_yin":
            print "  ---   ---"

        i = i - 1

    # Find hexagram numbers
    right = 0
    i, j, k = 1, 0, 0
    if options.verbose == False:
        while right < 7:
            if SHAPES[i][k] == primary_shape[j]:
                right = right + 1
                k = k + 1
                j = j + 1

                if k > 5:
                    print "     ", i
                    print " ", SHAPES[i][6]
                    break
            else:
                right = 0
                i = i + 1
                j, k = 0, 0
    else:
        while right < 7:
            if SHAPES[i][k] == primary_shape[j]:
                right = right + 1
                k = k + 1
                j = j + 1

                if k > 5:
                    print "     ", i
                    print " ", SHAPES[i][6]
                    print "\n", SHAPES[i][7]
                    break
            else:
                right = 0
                i = i + 1
                j, k = 0, 0

    # Print relating figure and find its number if needed
    if relating == True:
        print
        print "Relating Figure"

        rel = 5
        while rel >= 0:
            if hexagram[rel] == "old_yin":
                print "  ---------"
            elif hexagram[rel] == "old_yang":
                print "  ---   ---"
            elif hexagram[rel] == "young_yang":
                print "  ---------"
            elif hexagram[rel] == "young_yin":
                print "  ---   ---"

            rel = rel - 1

        right = 0
        i, j, k = 1, 0, 0

        if options.verbose == False:
            while right < 7:
                if SHAPES[i][k] == relating_shape[j]:
                    right = right + 1
                    k = k + 1
                    j = j + 1

                    if k > 5:
                        print "     ", i
                        print " ", SHAPES[i][6]
                        break
                else:
                    right = 0
                    i = i + 1
                    j, k = 0, 0
        else:
            while right < 7:
                if SHAPES[i][k] == relating_shape[j]:
                    right = right + 1
                    k = k + 1
                    j = j + 1

                    if k > 5:
                        print "     ", i
                        print " ", SHAPES[i][6]
                        print "\n", SHAPES[i][7]
                        break
                else:
                    right = 0
                    i = i + 1
                    j, k = 0, 0
        print

if __name__ == "__main__":
    main()

