# -*- coding:UTF-8 -*-

import re
import os
import sys
import upcean
import csv
from configparser import ConfigParser
import tkinter as tk
from tkinter import ttk
from tkinter import messagebox as mbox
from tkinter import filedialog as fdial
from PIL import ImageTk
import tkinter.scrolledtext as tkst


class MainWin(tk.Frame):

    def __init__(self, master):
        tk.Frame.__init__(self)
        master.geometry(set_size(master, 520, 450))
        master.resizable(False, True)
        master.title("Barcode generator v1.0")

        self.barcode_bg_color = (255, 255, 255)
        self.barcode_bar_color = (0, 0, 0)
        self.barcode_text_color = (0, 0, 0)
        self.barcode_list = {
            "EAN-13": "ean13",
            "EAN-8": "ean8",
            "EAN-5": "ean5"}
        self.bcsize = tk.IntVar()
        self.bctype = tk.StringVar()
        self.bcvalue = tk.StringVar()
        self.ean13start = self.ean08start = self.ean05start = ''
        self.existcomment = ''
        self.filedir = ''
        self.filetype = 'PNG'
        self.edited = False
        self.selected = ''
        self.oldvalue = ''

        self.master = master
        master.rowconfigure(1, weight=1)
        self.frameTopLeft = tk.Frame(master)
        self.frameTopLeft.grid(row=0, column=0, sticky='nw', padx=(10, 0))
        self.frameTopRight = tk.Frame(master, width=280)
        self.frameTopRight.grid(row=0, column=1, sticky='nsw', padx=(0, 0))
        self.frameTopRight.grid_propagate(False)
        self.frameMain = ttk.Frame(master)
        self.frameMain.grid(
            row=1, column=0, columnspan=2, sticky='nswe', padx=(
                10, 0), pady=(
                0, 10))

        # Menubar
        master.option_add('*tearOff', False)
        self.menubar = tk.Menu(master)
        master.config(menu=self.menubar)
        self.file = tk.Menu(self.menubar)
        tk.Menu(self.menubar)

        self.menubar.add_cascade(menu=self.file, label='File')

        self.file.add_command(label='Save as', command=self.saveasfile)
        self.file.add_command(label='Settings', command=self.settings)
        self.file.add_command(label='Info', command=self.helpwin)
        self.file.entryconfig('Save as', accelerator='Ctrl+S')

        # Entries
        self.frameType = ttk.Frame(self.frameTopLeft, padding=(5, 5))
        self.frameType.grid(
            row=0, column=0, sticky="nswe", padx=(
                0, 0), pady=(
                2, 2))
        ttk.Label(
            self.frameType,
            text='Barcode type:  ').grid(
            row=0,
            column=0,
            sticky='w',
            pady=(
                0,
                0))
        options = ['EAN-13', 'EAN-8', 'EAN-5']
        self.bcode_type = ttk.OptionMenu(
            self.frameType,
            self.bctype,
            options[0],
            *options,
            style='raised.TMenubutton')
        self.bcode_type.config(width=10)
        self.bcode_type.grid(row=0, column=1, sticky='we')

        self.frameSize = ttk.LabelFrame(
            self.frameTopLeft,
            text="Barcode size:",
            padding=(
                3,
                3))
        self.frameSize.grid(
            row=1, column=0, sticky="nswe", padx=(
                5, 5), pady=(
                2, 2))
        self.bcode_size = ttk.Scale(
            self.frameSize,
            value=1,
            from_=1,
            to=10,
            variable=self.bcsize,
            command=self.setscale)
        self.bcode_size.grid(row=0, column=0, sticky='we', pady=(5, 0))
        ttk.Label(
            self.frameSize,
            text='   1   2   3   4   5   6   7   8   9  10 ').grid(
            row=1,
            column=0,
            sticky='w')

        ttk.Label(
            self.frameTopLeft,
            text='Barcode value:').grid(
            row=2,
            column=0,
            sticky='w',
            padx=(
                5,
                0))
        self.bcode_val = ttk.Entry(
            self.frameTopLeft,
            width=17,
            textvariable=self.bcvalue,
            font=(
                'Arial',
                21))
        self.bcode_val.grid(row=3, column=0, pady=(0, 0))

        ttk.Label(
            self.frameTopLeft,
            text='Comment:').grid(
            row=4,
            column=0,
            sticky='w',
            padx=(
                5,
                0),
            pady=(
                5,
                0))
        self.textFrame = ttk.Frame(self.frameTopLeft, height=50, width=180)
        self.textFrame.grid(row=5, column=0, pady=(0, 0))
        self.textFrame.columnconfigure(0, weight=1)
        self.bcode_comment = tkst.ScrolledText(
            self.textFrame,
            wrap=tk.WORD,
            width=23,
            height=3,
            font=(
                'Arial',
                15))
        self.bcode_comment.grid(row=0, column=0, pady=(0, 0), sticky='we')

        # Buttons
        self.frameButton = ttk.Frame(self.frameTopRight)
        self.frameButton.grid(
            row=0, column=0, sticky="nswe", padx=(
                0, 5), pady=(
                5, 5))
        self.frameButton.grid_columnconfigure(0, weight=1)
        self.frameButton.grid_columnconfigure(1, weight=1)
        self.btnGenerate = ttk.Button(
            self.frameButton,
            text='Generate',
            command=self.generate)
        self.btnGenerate.grid(
            row=0, column=0, pady=(
                0, 0), padx=(
                0, 2), sticky="we")
        self.btnSave = ttk.Button(
            self.frameButton,
            text='Save',
            command=self.saveasfile)
        self.btnSave.grid(
            row=0, column=1, pady=(
                0, 0), padx=(
                2, 0), sticky="we")

        # Preview
        self.imagepanel = tk.Canvas(self.frameTopRight, width=250, height=175)
        self.imagepanel.configure(background='#c1c1c1')
        self.imagepanel.config(highlightbackground='#5f5f5f')
        self.vsb = ttk.Scrollbar(
            self.frameTopRight,
            orient="vertical",
            command=self.imagepanel.yview)
        self.hsb = ttk.Scrollbar(
            self.frameTopRight,
            orient="horizontal",
            command=self.imagepanel.xview)
        self.vsb.grid(row=1, column=1, sticky="nse")
        self.hsb.grid(row=2, column=0, sticky="sew")
        self.imagepanel.config(
            yscrollcommand=lambda f,
            l: self.autoscroll(
                self.vsb,
                f,
                l))
        self.imagepanel.config(
            xscrollcommand=lambda f,
            l: self.autoscroll(
                self.hsb,
                f,
                l))
        self.imagepanel.grid(
            row=1, column=0, sticky="nswe", padx=(
                0, 5), pady=(
                0, 5))

        # Table
        self.frameMain.rowconfigure(0, weight=1)
        self.tree = ttk.Treeview(self.frameMain, selectmode="extended", height=10, columns=("barcodes", "type",
                                                                                            "comment"),
                                 displaycolumns="barcodes type comment")
        self.tree.grid(row=0, column=0, sticky="ns", padx=(5, 5), pady=(5, 5))
        self.vsb1 = ttk.Scrollbar(
            self.frameMain,
            orient="vertical",
            command=self.tree.yview)
        self.hsb1 = ttk.Scrollbar(
            self.frameMain,
            orient="horizontal",
            command=self.tree.xview)
        self.vsb1.grid(row=0, column=1, sticky="nse")
        self.hsb1.grid(row=1, column=0, sticky="sew")
        self.tree.config(
            yscrollcommand=lambda f,
            l: self.autoscroll(
                self.vsb1,
                f,
                l))
        self.tree.config(
            xscrollcommand=lambda f,
            l: self.autoscroll(
                self.hsb1,
                f,
                l))
        self.tree.heading("#0", text="#")
        self.tree.heading("barcodes", text="Barcodes")
        self.tree.heading("type", text="Type")
        self.tree.heading("comment", text="Comment")

        self.tree.column(
            "#0",
            minwidth=20,
            width=55,
            stretch=True,
            anchor="center")
        self.tree.column(
            "barcodes",
            minwidth=50,
            width=120,
            stretch=True,
            anchor="center")
        self.tree.column(
            "type",
            minwidth=40,
            width=65,
            stretch=True,
            anchor="center")
        self.tree.column(
            "comment",
            minwidth=120,
            width=240,
            stretch=True,
            anchor="center")

        self.tree.tag_configure('even', background='#d9dde2')
        self.tree.bind('<Double-Button-1>', self.edit)
        master.bind("<Escape>", self.exit_ui)
        master.bind('<Control-s>', self.saveasfile)

        self.get_from_ini()
        self.read_file()

    def updatecomment(self, value=None):
        self.bcode_comment.delete(1.0, tk.END)
        if value:
            self.bcode_comment.insert(tk.END, value)

    def clearall(self):
        self.bcode_comment.delete(1.0, tk.END)
        self.bcode_val.delete(0, 'end')

    def edit(self, event):
        w = event.widget
        self.selected = w.focus()
        self.edited = True
        if self.selected:
            values = self.tree.set(self.selected)
            self.oldvalue = values['barcodes']
            self.bcvalue.set(values['barcodes'])
            self.updatecomment(values['comment'])
            self.bctype.set(values['type'])
            self.previewbarcode(values['barcodes'])

    def generate(self):
        if not self.bcvalue.get() or self.edited:
            print('@@@@@@@@@@@@@@@@@@@@@')
            self.clearall()
            if not self.GenerateCode():
                return False
        self.previewbarcode(self.bcode_val.get())
        self.edited = False

    def saveasfile(self, event=None):
        if self.bcode_val.get():
            if event:
                self.savebarcode(self.bcode_val.get())
            else:
                self.savebarcode(self.bcode_val.get(), True)
            self.updatetree()
        else:
            mbox.showwarning("Warning", "Generate any barcode first!")

    def generatebarcode(self, bcodevalue):
        tmpbarcode = upcean.oopfuncs.barcode(
            self.barcode_list[self.bctype.get()], self.bcode_val.get())
        tmpbarcode.size = self.bcode_size.get()
        tmpbarcode.barcolor = self.barcode_bar_color
        tmpbarcode.textcolor = self.barcode_text_color
        tmpbarcode.bgcolor = self.barcode_bg_color
        tmpbarcode.filename = None
        return tmpbarcode

    def previewbarcode(self, bcodevalue):
        tmpbarcode = self.generatebarcode(bcodevalue)
        validbc = tmpbarcode.validate_draw_barcode()
        if(validbc):
            image1 = ImageTk.PhotoImage(validbc)
            self.imagepanel.create_image(
                validbc.size[0] / 2, validbc.size[1] / 2, image=image1)
            self.imagepanel.config(
                scrollregion=(
                    0,
                    0,
                    validbc.size[0],
                    validbc.size[1]))
            self.imagepanel.image = image1
            self.already_exist(False, bcodevalue)
        else:
            mbox.showerror("Error", "Barcode couldn't be generated!")

    def savebarcode(self, bcodevalue, autoname=False):
        savestate = False
        fname = ""
        if autoname:
            fname = self.filedir + '/' + bcodevalue + '.' + self.filetype.lower()
        else:
            fname = fdial.asksaveasfilename(
                defaultextension='png',
                parent=self.master,
                title='Saving barcode',
                filetypes=[
                    ('PNG',
                     '*.png'),
                    ('JPEG',
                     '*.jpg *.jpeg'),
                    ('GIF',
                     '*.gif'),
                    ('Adobe PDF',
                     '*.pdf'),
                    ('Barcha fayllar',
                     '*.*')])
        if(fname):
            tmpbarcode = self.generatebarcode(bcodevalue)
            tmpbarcode.filename = fname
            savestate = tmpbarcode.validate_create_barcode()
            if(not savestate):
                mbox.showerror("Warning", "Barcode saving error")
            else:
                mbox.showinfo("Info", "Barcode is saved as file successfully")

    def updatetree(self):
        bcitem = self.getvalues()
        if self.isunique(bcitem[0]):
            idd = self.last_id() + 1
            self.tree.insert('', 'end', idd, text=idd, values=bcitem)
            self.tree.focus_set()
        else:
            if self.edited:
                if self.oldvalue == bcitem[0]:
                    self.tree.set(self.selected, 'comment', bcitem[2])
                    self.tree.selection_set(self.selected)
                else:
                    return self.already_exist()
            else:
                return self.already_exist()
        self.clearall()
        self.edited = False
        self.write_file()
        return True

    def already_exist(self, warn=True, bcode=None):
        if warn:
            mbox.showwarning("Warning", "Barcode is already in table!")
            return False
        else:
            if not self.isunique(bcode):
                self.updatecomment(self.existcomment)

    def last_id(self):
        if self.tree.get_children():
            idmax = max([int(i) for i in self.tree.get_children()])
        else:
            idmax = 0
        return idmax

    def getvalues(self):
        return self.bcvalue.get(), self.bctype.get(), self.bcode_comment.get(1.0, '1.end')

    def GenerateCode(self):
        if self.bctype.get() == 'EAN-13':
            if self.ean13start.isdigit() and len(self.ean13start) > 12:
                newcode = int(self.ean13start[:12])
                nextcode = False
                while nextcode == False:
                    if self.validate_ean13(newcode):
                        if self.isunique(
                                str(newcode) + str(self.validate_ean13(newcode))):
                            nextcode == True
                            break
                    newcode += 1
                self.bcvalue.set(str(newcode) +
                                 str(self.validate_ean13(newcode)))
                return True
            else:
                mbox.showwarning("Warning", "Enter initial value for EAN-13!")
                return False
        elif self.bctype.get() == 'EAN-8':
            if self.ean08start.isdigit() and len(self.ean08start) > 7:
                newcode = int(self.ean08start[:7])
                nextcode = False
                while nextcode == False:
                    if self.validate_ean08(newcode):
                        if self.isunique(
                                str(newcode) + str(self.validate_ean08(newcode))):
                            nextcode == True
                            break
                    newcode += 1
                self.bcvalue.set(str(newcode) +
                                 str(self.validate_ean08(newcode)))
                return True
            else:
                mbox.showwarning("Warning", "Enter initial value for EAN-08!")
                return False
        elif self.bctype.get() == 'EAN-5':
            if self.ean05start.isdigit() and len(self.ean05start) == 5:
                newcode = int(self.ean05start)
                nextcode = False
                while nextcode == False:
                    if self.isunique(str(newcode)):
                        nextcode == True
                        break
                    newcode += 1
                self.bcvalue.set(str(newcode))
                return True
            else:
                mbox.showwarning("Warning", "Enter initial value for EAN-05!")
                return False

    ##########################################################################
    ##                        GIU RELATED OPERATIONS                          ##
    ##########################################################################

    def exit_ui(self, event):
        self.master.quit()

    def setscale(self, var):
        value = self.bcode_size.get()
        if int(value) != value:
            self.bcode_size.set(round(value))

    def settings(self):
        SettingWin(self.master)
        self.get_from_ini()

    def helpwin(self):
        HelpWin(self.master)

    def autoscroll(self, sbar, first, last):
        """Hide and show scrollbar as needed."""
        first, last = float(first), float(last)
        if first <= 0 and last >= 1:
            sbar.grid_remove()
        else:
            sbar.grid()
        sbar.set(first, last)

    def zebra(self):
        childs = self.tree.get_children()
        if childs:
            n = 0
            for child in childs:
                n += 1
                if (n % 2 == 0):
                    tag = 'even'
                else:
                    tag = 'odd'
                self.tree.item(child, tags=(tag,))

    ##########################################################################
    ##                           FILE OPERATIONS                              ##
    ##########################################################################

    # Initializing from config.ini file
    def get_from_ini(self):
        self.config = ConfigParser()
        if not os.path.isfile('config.ini'):
            self.check_inifile()
        self.config.read('config.ini')
        sect = 'DefaultValues'
        try:
            if self.config.get(sect, 'Type'):
                self.bctype.set(self.config.get(sect, 'Type'))
            if self.config.get(sect, 'Size'):
                self.bcsize.set(self.config.get(sect, 'Size'))
            if self.config.get(sect, 'EAN13start'):
                self.ean13start = self.config.get(sect, 'EAN13start')
            if self.config.get(sect, 'EAN08start'):
                self.ean08start = self.config.get(sect, 'EAN08start')
            if self.config.get(sect, 'EAN05start'):
                self.ean05start = self.config.get(sect, 'EAN05start')
            if self.config.get(sect, 'filedirectory'):
                self.filedir = self.config.get(sect, 'filedirectory')
            if self.config.get(sect, 'FileType'):
                self.filetype = self.config.get(sect, 'FileType')
        except BaseException:
            mbox.showerror(
                "Warning",
                "Error occured while loading Config.ini!")

    # Checks and creates if ini file is not found
    def check_inifile(self):
        text = '[DefaultValues]\nType = EAN-13\nEAN13start = 4780000000010\nEAN08start = 47800010\nEAN05start = 00000\nSize = 2\nFileType = PDF\nFileDirectory ='
        file = open('config.ini', 'w')
        file.write(text)
        file.close()

    def write_file(self):
        if self.tree.get_children():
            with open('data.csv', 'w', encoding='utf-8') as file:
                fieldnames = ["id", "barcodes", "type", "comment"]
                writer = csv.DictWriter(
                    file, fieldnames=fieldnames, delimiter=";")
                writer.writeheader()
                for item in self.tree.get_children():
                    mydata = self.tree.set(item)
                    mydata["id"] = item
                    writer.writerow(mydata)
            self.zebra()

    def read_file(self):
        if os.path.isfile('data.csv'):
            try:
                with open('data.csv', encoding="utf-8") as csvfile:
                    reader = csv.DictReader(
                        csvfile, fieldnames=None, delimiter=";")
                    for row in reader:
                        self.tree.insert("", "end", row["id"], text=row["id"],
                                         values=[row["barcodes"], row["type"], row["comment"]])
                self.zebra()
            except BaseException:
                mbox.showerror(
                    "Error", "Error occured while loading Data.csv!")

    ##########################################################################
    ##                          BARCODE VALIDATIONS                           ##
    ##########################################################################

    def isunique(self, bcode):
        if os.path.isfile('data.csv'):
            with open('data.csv', encoding="utf-8") as csvfile:
                reader = csv.DictReader(
                    csvfile, fieldnames=None, delimiter=";")
                for row in reader:
                    if row["barcodes"] == bcode:
                        self.existcomment = row["comment"]
                        return False
                return True
        else:
            return True

    def validate_ean13(self, upc, return_check=False):
        upc = str(upc)
        if(len(upc) > 13):
            fix_matches = re.findall("^(\d{13})", upc)
            upc = fix_matches[0]
        if(len(upc) > 13 or len(upc) < 12):
            return False
        upc_matches = list(upc)
        upc_matches = [int(x) for x in upc_matches]
        upc_matches1 = upc_matches[0:][::2]
        upc_matches2 = upc_matches[1:][::2]
        EvenSum = (upc_matches2[0] + upc_matches2[1] + upc_matches2[2] +
                   upc_matches2[3] + upc_matches2[4] + upc_matches2[5]) * 3
        OddSum = upc_matches1[0] + upc_matches1[1] + upc_matches1[2] + \
            upc_matches1[3] + upc_matches1[4] + upc_matches1[5]
        AllSum = OddSum + EvenSum
        CheckSum = AllSum % 10
        if(CheckSum > 0):
            CheckSum = 10 - CheckSum
        if(not return_check and len(upc) == 13):
            if(CheckSum != upc_matches1[6]):
                return False
            if(CheckSum == upc_matches1[6]):
                return True
        if(return_check):
            return str(CheckSum)
        if(len(upc) == 12):
            return str(CheckSum)

    def validate_ean08(self, upc, return_check=False):
        upc = str(upc)
        if(len(upc) > 8):
            fix_matches = re.findall("^(\d{8})", upc)
            upc = fix_matches[0]
        if(len(upc) > 8 or len(upc) < 7):
            return False
        upc_matches = list(upc)
        upc_matches = [int(x) for x in upc_matches]
        upc_matches1 = upc_matches[0:][::2]
        upc_matches2 = upc_matches[1:][::2]
        EvenSum = (upc_matches1[0] + upc_matches1[1] +
                   upc_matches1[2] + upc_matches1[3]) * 3
        OddSum = upc_matches2[0] + upc_matches2[1] + upc_matches2[2]
        AllSum = OddSum + EvenSum
        CheckSum = AllSum % 10
        if(CheckSum > 0):
            CheckSum = 10 - CheckSum
        if(not return_check and len(upc) == 8):
            if(CheckSum != upc_matches2[3]):
                return False
            if(CheckSum == upc_matches2[3]):
                return True
        if(return_check):
            return str(CheckSum)
        if(len(upc) == 7):
            return str(CheckSum)


class SettingWin(tk.Frame):

    def __init__(self, master):
        tk.Frame.__init__(self)
        self.top = tk.Toplevel()
        self.top.resizable(False, False)
        self.top.geometry(set_size(self.top, 230, 330))
        self.top.title("Default settings")

        self.default_type = tk.StringVar()
        self.default_size = tk.IntVar()
        self.default_filetype = tk.StringVar()
        self.default_dir = tk.StringVar()
        self.ean13 = tk.StringVar()
        self.ean08 = tk.StringVar()
        self.ean05 = tk.StringVar()

        self.frameMain = ttk.Frame(self.top)
        self.frameMain.grid(row=0, column=0, sticky='nswe', padx=(10, 0))
        self.bottom = ttk.Frame(self.top)
        self.bottom.grid(row=1, column=0, sticky='nswe', padx=(10, 0))
        self.bottom.columnconfigure(0, weight=1)
        self.bottom.columnconfigure(1, weight=1)

        ttk.Label(
            self.frameMain,
            text='Barcode type: ').grid(
            row=0,
            column=0,
            sticky='w',
            pady=(
                5,
                0))
        options = ['EAN-13', 'EAN-8', 'EAN-5']
        self.dbctype = ttk.OptionMenu(
            self.frameMain,
            self.default_type,
            options[0],
            *options,
            style='raised.TMenubutton')
        self.dbctype.config(width=7)
        self.dbctype.grid(row=0, column=1, pady=(5, 0), sticky='we')
        ttk.Label(
            self.frameMain,
            text="Barcode size: ").grid(
            row=1,
            column=0,
            sticky='w',
            pady=(
                5,
                0))
        self.dbcsize = tk.Spinbox(
            self.frameMain,
            wrap=True,
            width=5,
            from_=1,
            to=10,
            textvariable=self.default_size)
        self.dbcsize.grid(row=1, column=1, pady=(5, 0), sticky='e')
        ttk.Label(
            self.frameMain,
            text="Default file type:").grid(
            row=2,
            column=0,
            sticky='w',
            pady=(
                5,
                0))
        filetypes = ['PDF', 'PNG', 'JPG', 'GIF']
        self.dcfiletype = ttk.OptionMenu(
            self.frameMain,
            self.default_filetype,
            filetypes[0],
            *filetypes)
        self.dcfiletype.config(width=7)
        self.dcfiletype.grid(row=2, column=1, sticky='we', pady=(5, 0))
        ttk.Label(self.frameMain, text='EAN-13 initial value:').grid(row=3,
                                                                     column=0, columnspan=2, sticky='w', pady=(5, 0))
        self.dean13 = ttk.Entry(
            self.frameMain,
            width=26,
            textvariable=self.ean13)
        self.dean13.grid(row=4, column=0, columnspan=2)
        ttk.Label(self.frameMain, text='EAN-08 initial value:').grid(row=5,
                                                                     column=0, columnspan=2, sticky='w', pady=(5, 0))
        self.dean08 = ttk.Entry(
            self.frameMain,
            width=26,
            textvariable=self.ean08)
        self.dean08.grid(row=6, column=0, columnspan=2)
        ttk.Label(self.frameMain, text='EAN-05 initial value:').grid(row=7,
                                                                     column=0, columnspan=2, sticky='w', pady=(5, 0))
        self.dean05 = ttk.Entry(
            self.frameMain,
            width=26,
            textvariable=self.ean05)
        self.dean05.grid(row=8, column=0, columnspan=2)

        self.framepdf = ttk.Frame(self.frameMain)
        self.framepdf.grid(row=9, column=0, columnspan=2)
        ttk.Label(
            self.framepdf,
            text='File saving directory:').grid(
            row=0,
            column=0,
            sticky='w',
            pady=(
                5,
                0))
        self.dfiledir = ttk.Entry(
            self.framepdf,
            width=20,
            textvariable=self.default_dir)
        self.dfiledir.grid(row=1, column=0, padx=(3, 0), pady=(5, 0))
        self.pdfbtn = ttk.Button(
            self.framepdf,
            text='...',
            width=3,
            command=self.folder)
        self.pdfbtn.grid(row=1, column=1, padx=(5, 0), pady=(5, 0))

        self.skpSave = ttk.Button(
            self.bottom,
            text='Save',
            command=self.save_list)
        self.skpSave.grid(
            row=0, column=0, sticky='we', padx=(
                0, 5), pady=(
                10, 3))
        self.btcancel = ttk.Button(
            self.bottom,
            text='Cancel',
            command=self.cancel)
        self.btcancel.grid(
            row=0, column=1, sticky='we', padx=(
                5, 0), pady=(
                10, 3))

        self.dbcsize.focus_set()

        self.top.bind('<Escape>', self.cancel)

        self.get_from_ini()

        self.top.grab_set()
        master.wait_window(self.top)

    def get_from_ini(self):
        self.partlist = []
        self.config = ConfigParser()
        self.config.read('config.ini')
        sect = 'DefaultValues'
        self.default_type.set(self.config.get(sect, 'Type'))
        self.default_size.set(self.config.get(sect, 'Size'))
        self.default_filetype.set(self.config.get(sect, 'FileType'))
        self.default_dir.set(self.config.get(sect, 'FileDirectory'))
        self.ean13.set(self.config.get(sect, 'EAN13start'))
        self.ean08.set(self.config.get(sect, 'EAN08start'))
        self.ean05.set(self.config.get(sect, 'EAN05start'))

    def update_list(self):
        self.name.delete(0, 'end')
        self.code.delete(0, 'end')
        self.address.delete(0, 'end')
        self.dockname.delete(0, 'end')
        self.pdfaddress.delete(0, 'end')
        self.name.insert(0, self.compname.get())
        self.code.insert(0, self.compcode.get())
        self.address.insert(0, self.compaddress.get())
        self.dockname.insert(0, self.dock.get())
        self.pdfaddress.insert(0, self.pdfdir.get())

    def folder(self):
        dirpath = fdial.askdirectory(mustexist=False,
                                     parent=self.master, title='Choose the folder')
        if dirpath:
            self.default_dir.set(dirpath)

    def save_list(self):
        sect = 'DefaultValues'
        self.config.set(sect, 'Type', self.default_type.get())
        self.config.set(sect, 'Size', self.dbcsize.get())
        self.config.set(sect, 'FileType', self.default_filetype.get())
        self.config.set(sect, 'FileDirectory', self.default_dir.get())
        self.config.set(sect, 'EAN13start', self.ean13.get())
        self.config.set(sect, 'EAN08start', self.ean08.get())
        self.config.set(sect, 'EAN05start', self.ean05.get())
        with open('config.ini', 'w') as configfile:
            self.config.write(configfile)
        self.top.destroy()

    def cancel(self, event=None):
        self.top.destroy()


class HelpWin(tk.Frame):

    def __init__(self, master):
        tk.Frame.__init__(self)
        self.top = tk.Toplevel()
        self.top.resizable(False, False)
        self.top.geometry(set_size(self.top, 220, 150))
        self.top.title("Info")

        ttk.Label(
            self.top, text='Barcode generator v1.0', font=(
                "Arial", 10, 'bold')).grid(
            row=0, column=0, padx=(
                10, 10), pady=(
                    15, 0), sticky='nswe')
        ttk.Label(
            self.top, text='Hamraqulov Boburmirzo © 2017').grid(
            row=1, column=0, padx=(
                10, 10), pady=(
                15, 0), sticky='nswe')
        ttk.Label(
            self.top, text='Telegram: @bzimor').grid(
            row=2, column=0, padx=(
                10, 10), pady=(
                5, 0), sticky='nswe')
        ttk.Label(self.top, text='Github: github.com/bzimor').grid(row=3,
                                                                   column=0, padx=(10, 10), pady=(5, 0), sticky='nswe')
        ttk.Label(
            self.top, text='Email: bobzimor@gmail.com').grid(
            row=4, column=0, padx=(
                10, 10), pady=(
                5, 0), sticky='nswe')

        self.top.grab_set()
        master.wait_window(self.top)


def set_size(win, w=0, h=0, absolute=True, win_ratio=None):
    winw = win.winfo_screenwidth()
    winh = win.winfo_screenheight()
    if not absolute:
        w = int(winw * win_ratio)
        h = int(winh * win_ratio)
        screen = "{0}x{1}+{2}+{3}".format(w,
                                          h,
                                          str(int(winw * 0.1)),
                                          str(int(winh * 0.05)))
    else:
        screen = "{0}x{1}+{2}+{3}".format(w,
                                          h,
                                          str(int((winw - w) / 2)),
                                          str(int((winh - h) / 2)))
    return screen


def resource_path(relative_path):
    """ Get absolute path to resource, works for dev and for PyInstaller """
    try:
        # PyInstaller creates a temp folder and stores path in _MEIPASS
        base_path = sys._MEIPASS
    except Exception:
        base_path = os.path.abspath(".")

    return os.path.join(base_path, relative_path).replace("\\", "/")


root = tk.Tk()
app = MainWin(root)
try:
    root.iconbitmap(default=resource_path('app.ico'))
except BaseException:
    pass

root.mainloop()