###########################################################
# RapydScript Standard Library
# Author: Alexander Tsepkov
# Copyright 2013 Pyjeon Software LLC
# License: Apache License   2.0
# This library is covered under Apache license, so that
# you can distribute it with your RapydScript applications.
###########################################################


str = JSON.stringify


###########################################################
# Python str object
###########################################################
class str(String):
    """
    This emulates Python str in JavaScript. The extra hackery here with
    toString() and valueOf() is needed because of poorly supported
    inheritance with native JavaScript objects
    """
    def __init__(self, elem=""):
        elem = String(elem)
        String.__init__(self, elem)
        self._str = elem

    def find(self, elem):
        return self._str.indexOf(elem)

    def strip(self):
        return str(self._str.trim())

    def lstrip(self):
        return str(self._str.trimLeft())

    def rstrip(self):
        return str(self._str.trimRight())

    def join(self, iterable):
        return str(iterable.join(self._str))

    def zfill(self, size):
        s = self._str # create a copy
        while s.length < size:
            s = '0' + s
        return str(s)

    def replace(self, orig, sub, n):
        s = self._str
        if n:
            for n in range(len(n)):
                s = String.replace(s, orig, sub)
        else:
            s = String.replace(s, RegExp(orig, 'g'), sub)
        return str(s)

    def toString(self):
        return self._str

    def toSource(self):
        # this method is only needed by Firefox
        return '"' + self._str + '"'

    def valueOf(self):
        return self._str

    def format(self, *args):
        s = self._str
        for i, a in enumerate(args):
            s.replace('{' + i + '}', a)
        return str(s)


###########################################################
# Python list object
###########################################################
class list(Array):
    """
    This class emulates a Python list in JavaScript
    """
    def __init__(self, iterable):
        for elem in iterable:
            Array.push(self, elem)

    def append(self, elem):
        self.push(elem)

    def find(self, elem):
        return self.indexOf(elem)

    def index(self, elem):
        val = self.find(elem)
        if val == -1:
            raise ValueError(str(elem) + " is not in list")
        return val

    def insert(self, index, elem):
        self.splice(index, 0, elem)

    def pop(self, index=len(self)-1):
        return self.splice(index, 1)[0]

    def extend(self, list2):
        self.push(*list2)

    def remove(self, elem):
        index = self.find(elem)
        self.pop(index)

    def copy(self):
        return list(self)

    def toSource(self):
        # a method needed only for Firefox, otherwise it craps out
        # this is a bit of a hack now, stringify doesn't return correct array representation
        return '[' + self + ']'


###########################################################
# Python dict object
###########################################################
# getOwnPropertyNames is not on Object's prototype chain for some reason, so we have to use
# this hack because of poor/inconsistent ECMAScript 'standard'
class dict(Object):
    """
    This class emulates a Python dict in JavaScript
    """
    def __init__(self, hashlike):
        for key in hashlike:
            self[key] = hashlike[key]

    def keys(self):
        if type(Object.getOwnPropertyNames) is 'function':
            # normal browsers
            return Object.getOwnPropertyNames(self)
        else:
            # IE and older browsers
            keys = []

            # Use a standard for in loop
            JS("""
            for (var x in self) {
                if (self.hasOwnProperty(x)) keys.push(x);
            }
            """)
            return keys

    def values(self):
        vals = []
        # using class' method instead of object's allows us to use these methods on other hashable types
        for key in dict.keys(self):
            vals.push(self[key])
        return vals

    def items(self):
        items = []
        # using class' method instead of object's allows us to use these methods on other hashable types
        for key in dict.keys(self):
            items.push((key, self[key]))
        return items

    def copy(self):
        return dict(self)

    def clear(self):
        # using class' method instead of object's allows us to use these methods on other hashable types
        for key in dict.keys(self):
            del self[key]
