import os
import math

import matplotlib.pyplot as pylab

class CopyrightTradeoff(object):
    cache_path = 'copyright_term'
    
    # config for plots
    amount = 10.0
    # slightly exaggerated decay rates to make things clearer
    cdrate = 0.9
    drate = 0.9
    num_years = 10
    years = range(0, 2*num_years, 2)
    past = [ -ii for ii in years ]
    production = [ amount ] * num_years
    today = [ amount * cdrate**ii for ii in years ]
    rtoday = list(today)
    rtoday.reverse()
    fullwidth = 0.8
    dw_width = fullwidth * 0.5
    barparams = { 'fc': 'blue', 'width': fullwidth, 'align': 'center',
            'alpha': '0.5'}

    ymax = 1.5 * amount

    def _xticks(self):
        tlabels =  ['Today'] + [''] * 3 + ['<------------- The Past ------------------']
        pylab.xticks(self.past, tlabels)
        pylab.xlim(xmax=2, xmin=self.past[-1]-2)
        pylab.figtext(0.1, 0.4, '.....', size='xx-large')

    def over_time(self):
        pylab.bar(self.past, self.production, **self.barparams)
        self._xticks()

    def over_time_with_decay(self):
        pylab.bar(self.past, self.today, **self.barparams)
        self._xticks()

    past_dw_xxs = [ xx + barparams['width']/2 for xx in past ]
    def tradeoff(self, startterm=3):
        def _showpd(term):

            termyear = self.past[term] + 1.25
            pylab.plot([termyear,termyear], [0,self.ymax], 'k')
            pylab.annotate('Public Domain', (self.past[-1], self.amount),
                    (termyear-3.5,self.amount))
            pylab.arrow(termyear-4, self.amount+0.2, -3, 0, head_width=0.2,
            fc='black', head_starts_at_zero=True)

        def _dw(term):
            # add offset for width of bar
            pylab.bar(self.past_dw_xxs[term:], self.today[term:], width=self.dw_width,
                    fc='red', alpha=0.5)

        self.over_time_with_decay()
        _showpd(startterm)
        _dw(startterm)
        self._xticks()
        self._savefig('over_time_tradeoff-%s-%s.png' % (startterm, 1))

        pylab.clf()

        # now with longer term
        self.over_time_with_decay()
        _showpd(startterm+1)
        _dw(startterm+1)

        # show old term
        oldtermyear = self.past[startterm] + 1.25
        pylab.plot([oldtermyear,oldtermyear+0.01], [0,self.ymax], 'k--')

        # extra production
        extras = [ 0.25/startterm * x for x in self.today ]
        newparams = dict(self.barparams)
        newparams['fc'] = 'yellow'
        pylab.bar(self.past, extras, bottom=self.today, **newparams)
        pylab.bar(self.past_dw_xxs[startterm+1:], extras[startterm+1:],
                bottom=self.today[startterm+1:], width=self.dw_width,
                fc='yellow', alpha=0.5)

        # extra d/w loss
        lostdw = self.past[startterm]+self.barparams['width']/2
        pylab.bar([lostdw], self.today[startterm], fc='black',
                width=self.dw_width)

        self._xticks()
        self._savefig('over_time_tradeoff-%s-%s.png' % (startterm, 2))

        pylab.bar([-3], [2*25/startterm**2], bottom=10, width=1, fc='yellow', alpha=0.5)
        pylab.bar([-4.5], [1.5*5/startterm], bottom=10, width=1, fc='black')
        self._savefig('over_time_tradeoff-%s-%s.png' % (startterm, 3))

    def revenue(self):
        pylab.bar(self.years, self.today , **self.barparams)

        def _xticks():
            tlabels =  ['Today'] + [''] * 3 + ['------------- The Future ------------------>']
            pylab.xticks(self.years, tlabels)
            pylab.xlim(xmin=-2, xmax=self.years[-1]+2)
            pylab.figtext(0.9, 0.4, '.....', size='xx-large')

        _xticks()
        self._savefig('over_time_for_revenue.png')

        rtoday_discounted =  [ xx*self.drate**ii for (ii,xx) in enumerate(self.today)
                ]
        newparams = dict(self.barparams)
        newparams['fc'] = 'red'
        pylab.bar(self.years, rtoday_discounted, **newparams)
        self._savefig('over_time_for_revenue_discounted.png')

        pylab.clf()
    
    fontsize = 'large'
    def works_to_welfare(self):
        import math
        xxs = range(0,100)
        vals = map(lambda x: math.log(x+1.0), xxs)
        pylab.bar(xxs, vals, 'k')
        pylab.xlabel('No. of Works', fontsize=self.fontsize)
        pylab.ylabel('Welfare', fontsize=self.fontsize)
        pylab.xticks([], [])
        pylab.yticks([], [])
        fn = 'works_to_welfare.png'
        fp = os.path.join(self.cache_path, fn)
        # pylab.savefig(fp, dpi=75)
        self._savefig(fn)

    def all(self):
        self.over_time()
        self._savefig('over_time.png')
        pylab.clf()

        self.over_time_with_decay()
        self._savefig('over_time_with_decay.png')
        pylab.clf()

        self.tradeoff(startterm=3)
        pylab.clf()
        self.tradeoff(startterm=6)
        pylab.clf()

        self.revenue()
        pylab.clf()
        self.works_to_welfare()
        pylab.clf()

    def _savefig(self, fn):
        if not os.path.exists(self.cache_path):
            os.makedirs(self.cache_path)
        fp = os.path.join(self.cache_path, fn)
        pylab.ylim(ymax=self.ymax)
        pylab.yticks([],[])

        # hack to get rid of axes ...
        ax = pylab.gca()
        ax.set_frame_on(False)
        # if you draw at 0 it does not work ??!
        pylab.axhline(0.01, color='k')

        # pylab.grid()
        fig = pylab.figure(1)
        fig.set_size_inches(10, 6)
        pylab.savefig(fp, dpi=75)

import optparse
import inspect
if __name__ == '__main__':
    methods = inspect.getmembers(CopyrightTradeoff, inspect.ismethod)
    methods = filter(lambda (name,y): not name.startswith('_'), methods)
    methods = dict(methods)

    usage = '''%prog {action}

action:
    '''
    usage += '\n    '.join(methods.keys())
    parser = optparse.OptionParser(usage)
    options, args = parser.parse_args()
    action = args[0]
    if not action in methods:
        print 'Invalid action: %s' % action
        parser.print_help()
        sys.exit(1)
    
    a = CopyrightTradeoff()
    getattr(a, action)()


